public void SendNotification(Guid SubscriptionId, string[] DataItems, string InstanceId, string[] TemplateIds, string[] PrimaryUserGuids, ActivityExecutionContext executionContext) { NotifyUser notice = new NotifyUser(); notice.SubscriptionId = SubscriptionId; notice.DataItems = DataItems; notice.InstanceId = InstanceId; notice.TemplateIds = TemplateIds; notice.PrimaryUserList = PrimaryUserGuids; notice.Execute(executionContext); }
//execute the Workflow to Notify the Assigned User protected override ActivityExecutionStatus Execute(ActivityExecutionContext TTUExecutionContext) { //since workflows only run on the workflow server, we can safely //connect and execute against the localhost EnterpriseManagementGroup emg = new EnterpriseManagementGroup("localhost"); //Get the classes we need to work with /* * get-scsmclass -name "System.WorkItem.TroubleTicket.AnalystCommentLog" | select name, id * get-scsmclass -name "System.WorkItem.TroubleTicket.UserCommentLog" | select name, id * get-scsmrelationshipclass -name "System.WorkItem.TroubleTicketHasAnalystComment" | select name, id * https://github.com/SMLets/SMLets/blob/55f1bac3bc7a7011a461b24f6d7787ba89fe2624/SMLets.Shared/Code/EntityTypes.cs#L120 * https://github.com/SMLets/SMLets/blob/55f1bac3bc7a7011a461b24f6d7787ba89fe2624/SMLets.Shared/Code/EntityTypes.cs#L161 */ ManagementPackClass UserCommentClass = emg.EntityTypes.GetClass(new Guid("a3d4e16f-5e8a-18ba-9198-d9815194c986")); ManagementPackClass UserClass = emg.EntityTypes.GetClass(new Guid("943d298f-d79a-7a29-a335-8833e582d252")); ManagementPackClass LocalizationClass = emg.EntityTypes.GetClass(new Guid("efa8bbd3-3fa4-2f37-d0d5-7a6bf53be7c8")); ManagementPackRelationship TroubleTicketHasUserCommentRelClass = emg.EntityTypes.GetRelationshipClass(new Guid("ce423786-16dd-da9c-fb7b-21ab5189e12b")); ManagementPackRelationship AssignedUserRelClass = emg.EntityTypes.GetRelationshipClass(new Guid("15e577a3-6bf9-6713-4eac-ba5a5b7c4722")); ManagementPackRelationship UserHasPreferenceRelClass = emg.EntityTypes.GetRelationshipClass(new Guid("649e37ab-bf89-8617-94f6-d4d041a05171")); //Get the Template GUID from the Translate MP EnterpriseManagementObject emoAdminSetting = emg.EntityObjects.GetObject <EnterpriseManagementObject>(new Guid("49a053e7-6080-e211-fd79-ca3607eecce7"), ObjectQueryOptions.Default); string templateID = emoAdminSetting[null, "TroubleTicketUserCommentTemplate"].Value.ToString(); bool isAzureTranslateEnabled; try { isAzureTranslateEnabled = Boolean.Parse(emoAdminSetting[null, "EnableAzureTranslate"].ToString()); } catch { isAzureTranslateEnabled = false; } //get the objects we'll need to work with starting with... //Comment object, the string/guid is an incoming parameter from the management pack //$commentObject = Get-SCSMObject -id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" Guid CommentGuid = new Guid(this.InstanceIds[0].ToString()); EnterpriseManagementObject CommentObject = emg.EntityObjects.GetObject <EnterpriseManagementObject>(CommentGuid, ObjectQueryOptions.Default); //Comment and Work Item relationship object //Using SMLets' Get-SCSMRelationshipObject -ByTarget parameter: https://github.com/SMLets/SMLets/blob/55f1bac3bc7a7011a461b24f6d7787ba89fe2624/SMLets.Shared/Code/EntityObjects.cs#L1853 //$WorkItemActionLogRelObject = Get-SCSMRelationshipObject -ByTarget $commentObject | ?{$_.relationshipid -eq "835a64cd-7d41-10eb-e5e4-365ea2efc2ea"} IList <EnterpriseManagementRelationshipObject <EnterpriseManagementObject> > CommentWorkItemRelObjects = emg.EntityObjects.GetRelationshipObjectsWhereTarget <EnterpriseManagementObject>(CommentObject.Id, ObjectQueryOptions.Default); EnterpriseManagementRelationshipObject <EnterpriseManagementObject> WorkItemActionLogRelObject = null; foreach (EnterpriseManagementRelationshipObject <EnterpriseManagementObject> relObject in CommentWorkItemRelObjects) { //if the relationship object has an ID that is the TroubleTicketHasUserCommentRelClass, then update the variable above with it if (relObject.RelationshipId.ToString() == TroubleTicketHasUserCommentRelClass.Id.ToString()) { //we now have the relationship object that contains the Comment and the Work Item WorkItemActionLogRelObject = relObject; break; } } //if the WorkItemActionLogRelObject is empty, we have a Service Request //end this workflow and let the other carry out if (WorkItemActionLogRelObject == null) { return(base.Execute(TTUExecutionContext)); } //Work Item object //Get-SCSMObject -id $WorkItemActionLogRelObject.SourceObject.Id EnterpriseManagementObject WorkItem = emg.EntityObjects.GetObject <EnterpriseManagementObject>(WorkItemActionLogRelObject.SourceObject.Id, ObjectQueryOptions.Default); //Assigned User relationship object IList <EnterpriseManagementRelationshipObject <EnterpriseManagementObject> > WorkItemRelUsers = emg.EntityObjects.GetRelationshipObjectsWhereSource <EnterpriseManagementObject>(WorkItem.Id, TraversalDepth.Recursive, ObjectQueryOptions.Default); EnterpriseManagementObject AssignedUser = null; foreach (EnterpriseManagementRelationshipObject <EnterpriseManagementObject> relObject in WorkItemRelUsers) { //if the relationship object has an ID that is the Assigned User and it isn't an old (isDeleted) user, then update the variable above with it if ((relObject.RelationshipId == AssignedUserRelClass.Id) && (relObject.IsDeleted == false)) { //we now have the relationship object that contains the Assigned User AssignedUser = relObject.TargetObject; break; } } //if the Assigned User exists, try and retrieve their Locale if (AssignedUser != null) { //Try to retrieve the Assigned User's Locale //Affected User's Preference relationship objects //https://github.com/SMLets/SMLets/blob/55f1bac3bc7a7011a461b24f6d7787ba89fe2624/SMLets.Shared/Code/EntityObjects.cs#L2775 //Get-SCSMRelatedObject -SMObject AffectedUser EnterpriseManagementObject AssignedUserLocale = null; //get the Assigned User's locale IList <EnterpriseManagementObject> AssignedUserPreferences = emg.EntityObjects.GetRelatedObjects <EnterpriseManagementObject>(AssignedUser.Id, TraversalDepth.OneLevel, ObjectQueryOptions.Default); foreach (EnterpriseManagementObject preference in AssignedUserPreferences) { if (preference.GetClasses()[0].Name == "System.UserPreference.Localization") { AssignedUserLocale = preference; break; } } //check if the Assigned User has a defined Locale, if they do and Azure Translate is enabled we can go ahead with a comparison. if ((AssignedUserLocale != null) && (isAzureTranslateEnabled)) { //get the Assigned User's locale string AssignedUserLocaleCode = AssignedUserLocale[(ManagementPackType)LocalizationClass, "LocaleID"].Value.ToString(); //get the Assigned User's language code //PowerShell equivalent: //[System.Globalization.Cultureinfo]::GetCultureInfo(LocaleCode).TwoLetterISOLanguageName string AssignedUserLangCode = System.Globalization.CultureInfo.GetCultureInfo(int.Parse(AssignedUserLocaleCode)).TwoLetterISOLanguageName.ToString().ToLower(); //now we need determine the language of the comment that was left //first, grab the Comment object and it's actual comment that was left //second, grab the person who entered the comment string CommentText = CommentObject[(ManagementPackType)UserCommentClass, "Comment"].Value.ToString(); string EnteredBy = CommentObject[(ManagementPackType)UserCommentClass, "EnteredBy"].Value.ToString(); int CommentFirstSentencePeriod = CommentText.IndexOf("."); //use a period to try to find the end of the first sentence to save on Azure spend //second, make the call to the Azure Translate class in this project to Detect the language code of the comment AzureCognitiveServicesTranslate languageManipulation = new AzureCognitiveServicesTranslate(); string CommentLangCode = null; string CommentLangDetectSample = null; int CommentLangDetectSamplePeriodIndex = CommentText.IndexOf("."); try { CommentLangDetectSample = CommentText.Substring(0, CommentLangDetectSamplePeriodIndex); } catch { CommentLangDetectSample = CommentText; } if (CommentLangDetectSample.Length > 1) { CommentLangCode = languageManipulation.LanguageDetect(emg, CommentLangDetectSample); } else { CommentLangCode = languageManipulation.LanguageDetect(emg, CommentText); } //if the detected Comment Language is different than that of the Assigned User then... //translate, leave the translated comment on the Action Log, notify on the new translated entry //this if statement would compare as seen below: //if ("en" != "es") if (CommentLangCode != AssignedUserLangCode) { //different languages //translate with Azure string translatedComment = languageManipulation.LanguageTranslate(emg, CommentLangCode, AssignedUserLangCode, CommentText); //create a New translated User Comment via projection/function from Rob Ford on TechNet //https://social.technet.microsoft.com/Forums/WINDOWS/en-US/1f06e71c-00f4-4cf7-9f7e-a9a78b4b907c/creating-action-log-entry-for-incident-via-sdk-in-c?forum=customization AddActionLogEntry newComment = new AddActionLogEntry(); string newCommentGuid = newComment.AddToActionLog(emg, WorkItem, translatedComment, EnteredBy, "UserCommentLog"); //notify on the new comment using the recently created comment's guid instead of the one that came in from the workflow parameter NotifyUser notification = new NotifyUser(); notification.SendNotification(this.SubscriptionId, this.DataItems, newCommentGuid, new String[] { templateID }, new String[] { AssignedUser.Id.ToString() }, TTUExecutionContext); } else { //same language //notify on the original comment NotifyUser notification = new NotifyUser(); notification.SendNotification(this.SubscriptionId, this.DataItems, this.InstanceIds[0].ToString(), new String[] { templateID }, new String[] { AssignedUser.Id.ToString() }, TTUExecutionContext); } } else { //the Affected user doesn't have a locale or Azure Translate isn't enabled, just notify them //notify the User NotifyUser notification = new NotifyUser(); notification.SendNotification(this.SubscriptionId, this.DataItems, this.InstanceIds[0].ToString(), new String[] { templateID }, new String[] { AssignedUser.Id.ToString() }, TTUExecutionContext); } } else { //the assigned user doesn't exist, so there isn't anyone to notify } return(base.Execute(TTUExecutionContext)); }