One of the most common complaints I’ve heard when creating work items from a template in Orchestrator is the lack of prefixes on the activities. This same problem exists when using SMLets to create a work item from a template. Since the Id is a key value there is no way to go back after it has been created and add the prefix. However, using Orchestrator, the SDK, and a little C#, you can work around this problem.
To do this you need to copy the Service Manager SDK binaries to your runbook server, then use the Run .Net Script activity in Orchestrator. In this example I will be creating a Service Request, but you could easily update the code for other classes. Also, due to the limitations of the Run .Net Script activity this only works for top level activities. So if you have parallel or sequential activities this will not update the activities inside of it. Although I am working on a work around for this, and will post the solution as soon as it is ready.
Update: I have released a stand alone executable that you can use to get around the problem of parallel and sequential activities. Click here for more details.
First start by copying the SDK Binaries folder from the Service Manager management server to your runbook server. If you have installed the Service Manager console, or SMLets on your runbook server, these may already be on your server. Once you have these on your runbook server you are ready to create your runbook.
In the code example here I am creating a Service Request by passing the template’s Guid to the Run .Net Script activity. This little bit of code will create the Service Request, then set the prefixes, and save. It will then output the SC Object Guid of the Service Request it created, so that you can use the standard SCSM integration pack activities to make any other required changes to the request.
- Start by adding a new Run .Net Script activity to you runbook.
- Then set the Type to C#.
- Next on the Advanced tab add the following Namespaces.
System
Microsoft.EnterpriseManagement
Microsoft.EnterpriseManagement.Common
Microsoft.EnterpriseManagement.Configuration - Then add the following references
C:\Microsoft.EnterpriseManagement.Core.dll (your path may be different based on where you copied the SDK binaries to)
C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll
C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.XML.dll
- On the Published Data tab, create a variable named strSRGuid
- Now you are ready to enter the C# code. On the details tab paste in the code below.
Guid TemplateId = new Guid("<guid passed in>"); EnterpriseManagementGroup emg = new EnterpriseManagementGroup("<SM Mgmt Srv>"); //Create Service Request ManagementPackObjectTemplate mpt = emg.Templates.GetObjectTemplate(TemplateId); EnterpriseManagementObjectProjection emop = new EnterpriseManagementObjectProjection(emg, mpt); //Get the service request prefix settings //Get the settings class ManagementPackClass mpc = emg.EntityTypes.GetClass(new Guid("fa662352-1660-33ae-6316-7fe1c9fecc6d")); //Get the emo for the settings EnterpriseManagementObject emo = emg.EntityObjects.GetObject<EnterpriseManagementObject>(mpc.Id, ObjectQueryOptions.Default); //Return prefix string prefix = emo[mpc, "ServiceRequestPrefix"].Value.ToString(); //Add prefix to ID string strSRID = prefix + emop.Object[null, "Id"].ToString(); emop.Object[null, "Id"].Value = strSRID; //Set Created Date emop.Object[null, "CreatedDate"].Value = DateTime.Now.ToUniversalTime(); ManagementPackRelationship relContainsActivity = emg.EntityTypes.GetRelationshipClass(new Guid("2da498be-0485-b2b2-d520-6ebd1698e61b")); foreach (IComposableProjection objCurComponent in emop[relContainsActivity.Target]) { // check all prefixes for activity EnterpriseManagementObject ActEmo = objCurComponent.Object; EnterpriseManagementObject objSettings = emg.EntityObjects.GetObject<EnterpriseManagementObject>(new Guid("5e04a50d-01d1-6fce-7946-15580aa8681d"), ObjectQueryOptions.Default); // set default prefix string Actprefix = objSettings[null, "SystemWorkItemActivityIdPrefix"].Value.ToString(); // check more specified activities // Get Activity Types ManagementPackClass MAc = emg.EntityTypes.GetClass(new Guid("7ac62bd4-8fce-a150-3b40-16a39a61383d")); ManagementPackClass RBc = emg.EntityTypes.GetClass(new Guid("5fe5d511-efb9-54a1-4be9-811f60e186c4")); ManagementPackClass RAc = emg.EntityTypes.GetClass(new Guid("bfd90aaa-80dd-0fbb-6eaf-65d92c1d8e36")); ManagementPackClass PAc = emg.EntityTypes.GetClass(new Guid("568c49f2-d7d6-d7d7-89dc-dfb5b39fded7")); ManagementPackClass SAc = emg.EntityTypes.GetClass(new Guid("0ad0812b-f267-52bf-9f11-c56587786791")); ManagementPackClass DAc = emg.EntityTypes.GetClass(new Guid("e786e1c7-b1fe-5b8b-ef8f-9e2dc346c44f")); if (ActEmo.IsInstanceOf(MAc)) { Actprefix = objSettings[null, "SystemWorkItemActivityManualActivityIdPrefix"].Value.ToString(); } else if (ActEmo.IsInstanceOf(RBc)) { Actprefix = objSettings[null, "MicrosoftSystemCenterOrchestratorRunbookAutomationActivityBaseIdPrefix"].Value.ToString(); } else if (ActEmo.IsInstanceOf(RAc)) { Actprefix = objSettings[null, "SystemWorkItemActivityReviewActivityIdPrefix"].Value.ToString(); } else if (ActEmo.IsInstanceOf(PAc)) { Actprefix = objSettings[null, "SystemWorkItemActivityParallelActivityIdPrefix"].Value.ToString(); } else if (ActEmo.IsInstanceOf(SAc)) { Actprefix = objSettings[null, "SystemWorkItemActivitySequentialActivityIdPrefix"].Value.ToString(); } else if (ActEmo.IsInstanceOf(DAc)) { Actprefix = objSettings[null, "SystemWorkItemActivityDependentActivityIdPrefix"].Value.ToString(); } //else if // check other types with same way string strActID = Actprefix + ActEmo[null, "Id"].Value.ToString(); ActEmo[null, "Id"].Value = strActID; } // Save SR emop.Overwrite(); strSRGuid = emop.Object.Id.ToString();
- You will need to provide the Guid of the template you want to use and the name of your Service Manager management server. On lines 1 and 2. Other than that you can leave the code as is.
The easiest way to get the Guid of the template is to use the Get-SCSMObjectTemplate PowerShell cmdlet. You could easily put this in another Run .Net Script prior to this one and pass in the Guid that way.