How to Get Project Type Guid of selected project in the Solution Explorer by using VS Package - vspackage

I've created the simple VS Package for adding new item in the context menu of solution explorer. In that I need to check Selected Project's Project Type GUID. How can i get this.
For example, One Solution contains the three different type of projects, like WindowFormsApplication, MVC Projects,WebApplication. While select the MVC Projects, we need to get that ProjectType GUID.
I've tried the followings in my Package.cs,
IVsMonitorSelection monitorSelection = (IVsMonitorSelection)Package.GetGlobalService(typeof(SVsShellMonitorSelection));
monitorSelection.GetCurrentSelection(out hierarchyPtr, out projectItemId, out mis, out selectionContainerPtr);
IVsHierarchy hierarchy = Marshal.GetTypedObjectForIUnknown(hierarchyPtr, typeof(IVsHierarchy)) as IVsHierarchy;
if (hierarchy != null)
{
object prjItemObject;
hierarchy.GetProperty(projectItemId, (int)__VSHPROPID.VSHPROPID_ExtObject, out prjItemObject);
string projectTypeGuid;
Project prjItem = prjItemObject as Project;
projectTypeGuid = prjItem.Kind;
}
In that I get GUID as "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC" for all selected Projects.
Could anyone please help me this?

I've found answer for this,
Reference: https://www.mztools.com/articles/2007/MZ2007016.aspx
public string GetProjectTypeGuids(EnvDTE.Project proj)
{
string projectTypeGuids = "";
object service = null;
Microsoft.VisualStudio.Shell.Interop.IVsSolution solution = null;
Microsoft.VisualStudio.Shell.Interop.IVsHierarchy hierarchy = null;
Microsoft.VisualStudio.Shell.Interop.IVsAggregatableProject aggregatableProject = null;
int result = 0;
service = GetService(proj.DTE, typeof(Microsoft.VisualStudio.Shell.Interop.IVsSolution));
solution = (Microsoft.VisualStudio.Shell.Interop.IVsSolution)service;
result = solution.GetProjectOfUniqueName(proj.UniqueName, out hierarchy);
if (result == 0)
{
aggregatableProject = (Microsoft.VisualStudio.Shell.Interop.IVsAggregatableProject)hierarchy;
result = aggregatableProject.GetAggregateProjectTypeGuids(out projectTypeGuids);
}
return projectTypeGuids;
}
public object GetService(object serviceProvider, System.Type type)
{
return GetService(serviceProvider, type.GUID);
}
public object GetService(object serviceProviderObject, System.Guid guid)
{
object service = null;
Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceProvider = null;
IntPtr serviceIntPtr;
int hr = 0;
Guid SIDGuid;
Guid IIDGuid;
SIDGuid = guid;
IIDGuid = SIDGuid;
serviceProvider = (Microsoft.VisualStudio.OLE.Interop.IServiceProvider)serviceProviderObject;
hr = serviceProvider.QueryService(ref SIDGuid, ref IIDGuid, out serviceIntPtr);
if (hr != 0)
{
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr);
}
else if (!serviceIntPtr.Equals(IntPtr.Zero))
{
service = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(serviceIntPtr);
System.Runtime.InteropServices.Marshal.Release(serviceIntPtr);
}
return service;
}
}
Its working fine for my requirement.

Related

How do I add an EPTimecardDetail record to a timecard?

I’m writing a customization to add records to a timecard and I’m trying to create a new record to add to the timecard. Using the logic in T230 I’m creating a variable and I’m being told by the compiler that EPTimecardDetail cannot be found.
I’ve added using PX.Objects.EP and PX.Objects.PM but I figure that if TimeCardMaint can be found then EPTimecardDetail should be able be found as well. I’ve included my using code as well but I think I’m missing something else.
using System;
using System.Collections;
using PX.Data;
using PX.Data.BQL.Fluent;
using PX.Data.BQL;
using PX.Objects.CS;
using PX.Objects.PM;
using PX.Objects.EP;
using PX.Objects.CR;
using PX.Objects.AR;
using PX.Objects.CT;
using PX.Objects.GL.FinPeriods;
using PX.TM;
using System.Collections.Generic;
namespace TimecardImport
{
public class NLTimecardLineEntry : PXGraph<NLTimecardLineEntry>
{
private static void DoPopulateTimeCard(Int32 employeeID, DateTime startDate, NLTimecardLine record)
{
TimeCardMaint graph = PXGraph.CreateInstance<TimeCardMaint>();
Int32 cardWeekID = PXWeekSelector2Attribute.GetWeekID(graph, startDate);
//look for an employee timecard with the current weekID
EPTimeCard card = PXSelectReadonly<EPTimeCard,
Where<EPTimeCard.employeeID, Equal<Required<EPTimeCard.employeeID>>,
And<EPTimeCard.weekId, Equal<Required<EPTimeCard.weekId>>>>>.SelectWindowed(graph, 0, 1, employeeID, cardWeekID);
if (card == null) //if a card was not found, create one
{
card = (EPTimeCard)graph.Document.Cache.CreateInstance();
card.WeekID = cardWeekID;
card.EmployeeID = employeeID;
card = graph.Document.Insert(card);
}
//at this point card is the card that we're going to work with
var detailLine = (EPTimecardDetail)graph.Activities.Cache.CreateCopy(
graph.Activities.Insert());
//detailLine.SetValueExt<detailLine.Date_Date>(record, record.InDate);
//detailLine.EarningTypeID = "RG";
//detailLine = graph.Activities.Update(detailLine);
graph.Save.Press();
}
}}
The error I'm getting is "The type or namespace name 'EPTimecardDetail' could not be found (are you missing a using directive or an assembly reference?)".
EPTimecardDetail is defined within PX.Objects.EP so I'm not sure why I'm having a problem there. Or, perhaps this is not the way to add records to the Details tab of the Employee Time Card screen?
For the namespace issue you can declare using PX.Object.EP and refer to the type as TimeCardMaint.EPTimecardDetail
Or you can declare using static PX.Objects.EP.TimeCardMaint and refer to the type as EPTimecardDetail
For inserting the record check the source code in file TimeCardMaint.cs There are examples on how to insert this DAC record.
Make sure the fields used for SQL joins like OrigNoteID and RefNoteID have the proper value (non null).
This example is from the Correct action in TimeCardMaint:
[PXUIField(DisplayName = Messages.Correct)]
[PXButton(ImageKey = PX.Web.UI.Sprite.Main.Release)]
public virtual IEnumerable Correct(PXAdapter adapter)
{
if (Document.Current != null)
{
EPTimeCard source = GetLastCorrection(Document.Current);
if (source.IsReleased != true)
return new EPTimeCard[] { source };
EPTimeCard newCard = (EPTimeCard)Document.Cache.CreateInstance();
newCard.WeekID = source.WeekID;
newCard.OrigTimeCardCD = source.TimeCardCD;
newCard = Document.Insert(newCard);
newCard.EmployeeID = source.EmployeeID;
PXNoteAttribute.CopyNoteAndFiles(Document.Cache, source, Document.Cache, newCard, true, true);
bool failed = false;
Dictionary<string, TimeCardSummaryCopiedInfo> summaryDescriptions = new Dictionary<string, TimeCardSummaryCopiedInfo>();
foreach (EPTimeCardSummary summary in Summary.View.SelectMultiBound(new object[] { source }))
{
string key = GetSummaryKey(summary);
if (!summaryDescriptions.ContainsKey(key))
{
string note = PXNoteAttribute.GetNote(Summary.Cache, summary);
var info = new TimeCardSummaryCopiedInfo(summary.Description, note);
summaryDescriptions.Add(key, info);
}
}
foreach (EPTimecardDetail act in TimecardActivities.View.SelectMultiBound(new object[] { source }))
{
EPTimecardDetail newActivity = PXCache<EPTimecardDetail>.CreateCopy(act);
newActivity.Released = false;
newActivity.Billed = false;
newActivity.NoteID = null;
newActivity.TimeCardCD = null;
newActivity.TimeSheetCD = null;
newActivity.OrigNoteID = act.NoteID; //relation between the original activity and the corrected one.
newActivity.Date = act.Date;
newActivity.Billed = false;
newActivity.SummaryLineNbr = null;
newActivity.NoteID = null;
newActivity.ContractCD = null;
isCreateCorrectionFlag = true;
try
{
newActivity = Activities.Insert(newActivity);
}
catch (PXSetPropertyException ex)
{
failed = true;
Activities.Cache.RaiseExceptionHandling<EPTimecardDetail.summary>(act, act.Summary, new PXSetPropertyException(ex.MessageNoPrefix, PXErrorLevel.RowError));
continue;
}
newActivity.TrackTime = act.TrackTime; //copy as is.
isCreateCorrectionFlag = false;
newActivity.ApprovalStatus = ActivityStatusAttribute.Completed;
newActivity.RefNoteID = act.NoteID == act.RefNoteID ? newActivity.NoteID : act.RefNoteID;
newActivity.ContractCD = act.ContractCD;
PXNoteAttribute.CopyNoteAndFiles(Activities.Cache, act, Activities.Cache, newActivity);
Activities.Cache.SetValue<EPTimecardDetail.isCorrected>(act, true);
Activities.Cache.SetStatus(act, PXEntryStatus.Updated);
}
if (failed)
{
throw new PXException(Messages.FailedToCreateCorrectionTC);
}
foreach (EPTimeCardItem item in Items.View.SelectMultiBound(new object[] { source }))
{
EPTimeCardItem record = Items.Insert();
record.ProjectID = item.ProjectID;
record.TaskID = item.TaskID;
record.Description = item.Description;
record.InventoryID = item.InventoryID;
record.CostCodeID = item.CostCodeID;
record.UOM = item.UOM;
record.Mon = item.Mon;
record.Tue = item.Tue;
record.Wed = item.Wed;
record.Thu = item.Thu;
record.Fri = item.Fri;
record.Sat = item.Sat;
record.Sun = item.Sun;
record.OrigLineNbr = item.LineNbr;//relation between the original activity and the corrected one.
}
foreach (EPTimeCardSummary summary in Summary.Select())
{
string key = GetSummaryKey(summary);
if (summaryDescriptions.ContainsKey(key))
{
PXNoteAttribute.SetNote(Summary.Cache, summary, summaryDescriptions[key].Note);
Summary.Cache.SetValue<EPTimeCardSummary.description>(summary, summaryDescriptions[key].Description);
}
}
return new EPTimeCard[] { newCard };
}
return adapter.Get();
}

How to get Opportunity Relations in Sales Order

In Opportunity screen, the definition of the data view for Relations is simply :
public CRRelationsList<CROpportunity.noteID> Relations;
When a Sales Order is raised from the Opportunity. I'd like to display the Relations defined from the source Opporunity in another tab. And I'm just struggling how to write the the data view and pass the Opportunity noteid.
public CRRelationsList<???>Relations;
Thanks !
The generic type in dataviews often resolve to the current record.
In CRRelationsList class the generic type is named TNoteField:
public class CRRelationsList<TNoteField> : PXSelect<CRRelation>
where TNoteField : IBqlField
ssuming the dataview is declared as CRRelationsList<CROpportunity.noteID>.
The generic type value will be resolved like this Caches[typeof(CROpportunity)].Current.NoteID.
protected virtual void CRRelation_RefNoteID_FieldDefaulting(PXCache sender, PXFieldDefaultingEventArgs e)
{
// Get a cache object of type CROpportunity
var refCache = sender.Graph.Caches[BqlCommand.GetItemType(typeof(TNoteField))];
// Get the NoteID field value of the current CROpportunity object
e.NewValue = refCache.GetValue(refCache.Current, typeof(TNoteField).Name);
}
So to set DAC.Field of CRelationsList<DAC.field> you would do:
// In a graph extension (PXGraphExtension)
Base.Caches[typeof(DAC)].Current.Fied = ???;
// Or in graph (PXGraph)
Caches[typeof(DAC)].Current.Fied = ???;
If current DAC object is null you need to insert a record in a dataview or directly in the cache object.
I'm not sure re-using CRRelationsList list is the best approach if you want to simply display records because it does much more than that. It should be possible to extract the select request out of it and directly substitute the TNoteField value:
private static PXSelectDelegate GetHandler()
{
return () =>
{
var command = new Select2<CRRelation,
LeftJoin<BAccount, On<BAccount.bAccountID, Equal<CRRelation.entityID>>,
LeftJoin<Contact,
On<Contact.contactID, Equal<Switch<Case<Where<BAccount.type, Equal<BAccountType.employeeType>>, BAccount.defContactID>, CRRelation.contactID>>>,
LeftJoin<Users, On<Users.pKID, Equal<Contact.userID>>>>>,
Where<CRRelation.refNoteID, Equal<Current<TNoteField>>>>();
var startRow = PXView.StartRow;
int totalRows = 0;
var list = new PXView(PXView.CurrentGraph, false, command).
Select(null, null, PXView.Searches, PXView.SortColumns, PXView.Descendings, PXView.Filters,
ref startRow, PXView.MaximumRows, ref totalRows);
PXView.StartRow = 0;
foreach (PXResult<CRRelation, BAccount, Contact, Users> row in list)
{
var relation = (CRRelation)row[typeof(CRRelation)];
var account = (BAccount)row[typeof(BAccount)];
relation.Name = account.AcctName;
relation.EntityCD = account.AcctCD;
var contact = (Contact)row[typeof(Contact)];
if (contact.ContactID == null && relation.ContactID != null &&
account.Type != BAccountType.EmployeeType)
{
var directContact = (Contact)PXSelect<Contact>.
Search<Contact.contactID>(PXView.CurrentGraph, relation.ContactID);
if (directContact != null) contact = directContact;
}
relation.Email = contact.EMail;
var user = (Users)row[typeof(Users)];
if (account.Type != BAccountType.EmployeeType)
relation.ContactName = contact.DisplayName;
else
{
if (string.IsNullOrEmpty(relation.Name))
relation.Name = user.FullName;
if (string.IsNullOrEmpty(relation.Email))
relation.Email = user.Email;
}
}
return list;
};
}

call log function in windows phone 8

I am developing VoIP application (Dialler) in windows phone 8, In that application contain dial pad , contacts, call log , I already create a dial pad and contact list, I need to develop a call log function in that application. I struggle in to create a call log for windows phone 8 any help please
This is a class that creates an XML file which holds the logs of all calls. You didn't specify the question enough or what you want to do, or what have you already tried. So here is an idea of what you should implement:
public class Logger
{
private static string logPath;
public Logger()
{
logPath = "/Logs/log.xml";
}
public void LogData(string contactName, string duration)
{
Object thisLock = new Object();
logPath += DateTime.Now.ToShortDateString().Replace('.', '_') + ".log";
XmlDocument doc = new XmlDocument();
lock (thisLock)
{
try
{
XmlNode root = null;
if (File.Exists(logPath))
{
doc.Load(logPath);
root = doc.SelectSingleNode("/Call");
}
else
{
doc.AppendChild(doc.CreateXmlDeclaration("1.0", "UTF-8", null));
root = doc.AppendChild(doc.CreateElement("Call"));
}
XmlElement call = doc.CreateElement("call");
root.AppendChild(call);
XmlElement xcontactName = doc.CreateElement("contactName");
xcontactName.InnerText = contactName;
call.AppendChild(xcontactName);
XmlElement xdate = doc.CreateElement("date");
xdate.InnerText = DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss");
call.AppendChild(xdate);
XmlElement xduration = doc.CreateElement("duration");
xduration.InnerText = duration;
call.AppendChild(xduration);
doc.Save(logPath);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
}

Creating a new entity with a field of type optionset

I have an html form which does a post to an aspx page which uses the SOAP web services to connect to CRM. The code behind the page creates an entity in the CRM. I am using the IOrganizationService in my code behind.
The code looks like
IOrganizationService service = (IOrganizationService)serviceProxy;
Entity lead = new Entity("lead");
string fieldValue = string.Empty;
foreach (string key in Request.Form.AllKeys)
{
if (key.Equals(SubmitKey, StringComparison.InvariantCultureIgnoreCase) == false &&
key.Equals(CRMHostKey, StringComparison.InvariantCultureIgnoreCase) == false &&
key.Equals(redirectErrorURLKey, StringComparison.InvariantCultureIgnoreCase) == false &&
key.Equals(redirectSuccessURLKey, StringComparison.InvariantCultureIgnoreCase) == false)
{
if (!string.IsNullOrEmpty(Request.Form[key]))
{
fieldValue = Request.Form[key].Trim();
}
else
{
fieldValue = string.Empty;
}
if (key.Equals("new_contacttypechoices", StringComparison.InvariantCultureIgnoreCase))
{
lead[key] = new KeyValuePair<string, int>("Email", 100000000);
//OptionMetadata objOM = GetOptionMetadata("lead", "new_contacttypechoices", fieldValue, service);
//lead[key] = objOM;
//lead[key] = 100000000; //Incorrect attribute value type System.Int32
//lead[key] = fieldValue; //Incorrect attribute value type System.String
}
else
{
lead[key] = fieldValue;
}
}
newLeadID = service.Create(lead);
}
Screenshot of the field
I get an error when I try
lead[key] = fieldValue
I get an error when I try
lead[key] = 100000000
I get an error when I try
lead[key] = new KeyValuePair<string, int>("Email", 100000000);
I get an error when I get the OptionMetaData and set that to the entity. Any ideas on how to create an entity using an optionset?
Thanks
Depends on the error you are getting, but if lead is of type Microsoft.Xrm.Sdk.Entity, it could be that you need to either replace an existing value or add a new one.
if (lead.Attributes.Contains(key))
{
lead[key] = new OptionSetValue(100000000);
}
else
{
lead.Attributes.Add(key, new OptionSetValue(100000000));
}
Rereading I notice you have put (presumably) the errors in comments. In that case, I suggest the issue is that you need to assign a value of type OptionSetValue

Check if a List Column Exists using SharePoint Client Object Model?

Using the Client Object Model (C#) in SharePoint 2010, how can I determine if a specified column (field) name exists in a given List?
Thanks, MagicAndi.
Just found this while searching for the same thing, but it looks like Sharepoint 2010 has something built in for this, at least for the Server model: list.Fields.ContainsField("fieldName");
Not sure if it exists for Client side though. Figured it would be a good place to store this information however.
Server Object Model
string siteUrl = "http://mysite";
using (SPSite site = new SPSite(siteUrl))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["my forum"];
for (int i = 0; i < list.Fields.Count; i++)
{
if (list.Fields[i].Title == "xyz")
{
-
-
}
}
}
}
Client Object Model
string siteUrl = "http://MyServer/sites/MySiteCollection";
ClientContext clientContext = new ClientContext(siteUrl);
SP.List List = clientContext.Web.Lists.GetByTitle("my forum");
for (int i = 0; i < list.Fields.Count; i++)
{
if (list.Fields[i].Title == "xyz")
{
-
-
}
}
The following method demonstrates how to determine whether a specified column exists in a List using CSOM:
static class FieldCollectionExtensions
{
public static bool ContainsField(this List list,string fieldName)
{
var ctx = list.Context;
var result = ctx.LoadQuery(list.Fields.Where(f => f.InternalName == fieldName));
ctx.ExecuteQuery();
return result.Any();
}
}
Usage
using(var ctx = new ClientContext(webUrl))
{
var list = ctx.Web.Lists.GetByTitle(listTitle);
if(list.ContainsField("Title")){
//...
}
}
Here's an extension code (CSOM) for sharepoint list
public static bool DoesFieldExist(this List list, ClientContext clientContext, string internalFieldname)
{
bool exists = false;
clientContext.Load(list.Fields, fCol => fCol.Include(
f => f.InternalName
).Where(field => field.InternalName == internalFieldname));
clientContext.ExecuteQuery();
if (list.Fields != null && list.Fields.Count > 0)
{
exists = true;
}
return exists;
}
usage
List targetList = this.Context.Web.Lists.GetById(<ListID>);
targetList.DoesFieldExist(<ClientContext>, <Field internal Name>)
enjoy :)
I ended up retrieving the details of the list's fields prior to my operation, and saving them in a generic list of structs (containing details of each field). I then query this (generic) list to see if the current field actually exists in the given (SharePoint) list.
// Retrieve detail sof all fields in specified list
using (ClientContext clientContext = new ClientContext(SharePointSiteUrl))
{
List list = clientContext.Web.Lists.GetByTitle(listName);
_listFieldDetails = new List<SPFieldDetails>();
// get fields name and their types
ClientObjectPrototype allFields = list.Fields.RetrieveItems();
allFields.Retrieve( FieldPropertyNames.Title,
FieldPropertyNames.InternalName,
FieldPropertyNames.FieldTypeKind,
FieldPropertyNames.Id,
FieldPropertyNames.ReadOnlyField);
clientContext.ExecuteQuery();
foreach (Field field in list.Fields)
{
SPFieldDetails fieldDetails = new SPFieldDetails();
fieldDetails.Title = field.Title;
fieldDetails.InternalName = field.InternalName;
fieldDetails.Type = field.FieldTypeKind;
fieldDetails.ID = field.Id;
fieldDetails.ReadOnly = field.ReadOnlyField;
listFieldDetails.Add(fieldDetails);
}
}
// Check if field name exists
_listFieldDetails.Exists(field => field.Title == fieldName);
// Struct to hold details of the field
public struct SPFieldDetails
{
public string Title { get; set; }
public string InternalName { get; set; }
public Guid ID { get; set; }
public FieldType Type { get; set; }
public bool ReadOnly { get; set; }
}
Some good answers above. I personally used this one:
List list = ctx.Web.Lists.GetByTitle("Some list");
FieldCollection fields = list.Fields;
IEnumerable<Field> fieldsColl = ctx.LoadQuery(fields.Include(f => f.InternalName));
ctx.ExecuteQuery();
bool fieldMissing = fieldsColl.Any(f => f.InternalName != "Internal_Name");
You can also use 'Where' after Include method and check if returned collection/field is null. It's about personal preference, because both options are querying on client side.
I prefer the SharePoint Plus Library as it is really clean:
http://aymkdn.github.io/SharepointPlus/symbols/%24SP%28%29.list.html
$SP().list("My List").get({
fields:"Title",
where:"Author = '[Me]'"
},function getData(row) {
console.log(row[0].getAttribute("Title"));
});
You could setup a for loop to loop through the row and check if the column you're looking for exists.
A cut down and simplified version of Mitya's extension method:
public static bool FieldExists(this List list, string internalFieldname)
{
using (ClientContext clientContext = list.Context as ClientContext)
{
clientContext.Load(list.Fields, fCol => fCol.Include(
f => f.InternalName
).Where(field => field.InternalName == internalFieldname));
clientContext.ExecuteQuery();
return (list.Fields != null) && (list.Fields.Count > 0);
}
}
There's no need to pass in a separate client context parameter when you can already use the context that comes in with the list.
to much code use this
load Fields first then
bool exists= clientContext2.Site.RootWeb.Fields.Any(o => o.Id.ToString() == a.Id.ToString());

Resources