Activity prefixes for Cloud and Delay Activity
Recently we created some templates with Delay Activities and/or Cloud Activities. What I noticed is, that these 2 activities have no Activity prefixes when created - Powershell Activities have the standard AC...
Is it somehow possible to add the AC or maybe custom Prefixes for these activities, as only numbers feels a bit odd to me. :D
Best Answer
-
Justin_Workman Cireson Support Super IT Monkey ✭✭✭✭✭
@Simon_Zeinhofer - I have raised PR126928 for this issue. Thanks for reporting it!
0
Answers
@Simon_Zeinhofer - I have raised PR126928 for this issue. Thanks for reporting it!
Thank you @Justin_Workman :)
Any updates on this? I've recently been working on having a RO that runs a powershell activity that creates related SRs. It applies a template to those SRs, and when the template is applied all the contained activities are mixing their prefixes.
This wouldn't be problematic if it didn't cause my approval emails to fail as not having a prefix causes the reply to emails to not route back to the approval activity, but instead creates an incident.
I believe it may related to Simon's issue as the behavior sounds similar.
@Simon_Zeinhofer I found this which has worked to at least add the prefix RA to my activities. I imagine it will work for all default activity types. I'm trying to get it working for cireson activities as well, but I must be making a mistake in the if statements at the top of the function.
Set-SCSMTemplateWithActivities powershell script – CTGlobal (ctglobalservices.com)
I added the top two lines to the if block, but I'm guessing the class i'm calling is not correct as it's not applying any prefix.
You can see the results of applying the templates/ activities using the linked script below.
Hope that helps.
Hy @Bryan_Lalor,
we already use an apply-Template function where all Activity prefixes are applied. But as far as I remember, this function had the problem with non existing prefixes too, as well as activities not going to In Progress. But this error has been fixed long ago :) In case you need a definite working apply-template function, have a look at @Adam_Dzyacky s Smlet Exchange Connector, it has the working function in it :) And the good thing is, you can add every activitiy + prefix to it by just adding it to the if-else clause ;)
So in short, when using the apply-template we already included the cloud,delay and powershell activities and there the prefixes are added. We only have the situation when the work item is created via an RO. But tbh for us it is only visual, as the functionality is given still.
In your case it cannot work, as the top if condition says
So the other if-else clauses will only trigger, when the Activitiy Classname starts with the standard activity prefix or is an SCO activity. As Cireson activity Classnames start with "Cireson" no prefix will be applied, as the top if condition does not return $true. If you remove that if condition it will work fine ;)
Ah, appreciate the reply and information. I was aware of the smletsexchange connector having that functionality, but wasn't aware I could leverage the exchangeconnector without needing to have its input be a mailed message.
If that is the only method that wouldn't work for my specific need as i'm passing the userinput from the originating ticket to the child tickets it created.
I did have the issue with activities not progressing but resolved that by just passing "New" in the splat for the ticket creation.
@Bryan_Lalor I meant you could just copy the function from it and use it for your needs :)
Sorry I don't understand what you mean with that. You mean you need a function to copy the needed userinput from a parent workitem to a Child workitem? If that's the case I can help you out with a function I wrote ;)
I just read in the comments that there was a problem with activities not going In Pgress, but never experienced it myself when using it.
I had misunderstood what you were suggesting.
I'm not having any issues with passing the Userinput for my script. It is just a requirement for what I'm trying to accomplish. My current to dos are:
Setting the relationship with the parent service request.
Fixing prefixes. (I just tested adding additional -or conditions to the function to account for Cireson activities with no luck.) Going to see what I'll need to do to adapt Adam's version. It's mostly a vanity issue as the linked script functions for adding RA to review activities which was the most important part for me, but I think it's worth fixing in case I need to use those prefixes in the future for further automation or data lookups.
@Bryan_Lalor If you need help passing the userinput from one workitem to the other, just text me ;)
For the apply function: remove the first if condition completely.
@Simon_Zeinhofer I went ahead and joined the changes made to this original script by @Adam_Dzyacky and the original script to make something that can be utilized with a powershell activity.
Also Adam's script in the exchange connector doesn't account for Cireson notification activities.
I added that to the function Get-SCSMWorkItemSetting and updated the if statement in function Update-SCSMPropertyCollection to account for it.
# //***************************************************************************
# // Authors: Morten Meisler, Adam Dzyacky@Adam_Dzyacky, Bryan O'Leathlobhair
# // Original by Morten Meisler found here https://blog.ctglobalservices.com/service-manager-scsm/mme/set-scsmtemplatewithactivities-powershell-script/
# // Usage: Script to apply a template with activities on a workitem and correct
# // id prefixes on each activity
# //
# //
# // History:
# // 1.0 27/12/2013 beta version 1.
# // 1.1 02-01-2014 Fixed issue with activities containing other objects (like system.reviewer)
# // 1.2 02-13-2024 Joined the functonality implimeneted by AdhocAdam's exchange connector to allow for adding in Cireson Activity Prefixes
# //***************************************************************************
Param ([guid]$Id =$(throw "Please provide guid of the workitem"),
[string]$TemplateDisplayName,
[guid]$TemplateId,
[string]$workItemClass,
[string]$ComputerName = "localhost")
#Function for getting all work item settings necessary.
$scsmMGMTParams = @{ ComputerName = $ComputerName }
function Get-SCSMWorkItemSetting {
param (
#A string of an SCSM Class Name
[Parameter()]
[string]$WorkItemClass
)
switch ($WorkItemClass) {
"System.WorkItem.Incident" {
$settingCls = Get-ScsmClass @scsmMGMTParams -Name "System.WorkItem.Incident.GeneralSetting$"
$settings = $settingCls | Get-ScsmObject @scsmMGMTParams
$maxAttach = $settings.MaxAttachments
$maxSize = $settings.MaxAttachmentSize
$prefix = $settings.PrefixForId
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"System.WorkItem.ServiceRequest" {
$settingCls = Get-ScsmClass @scsmMGMTParams -Name "System.GlobalSetting.ServiceRequestSettings$"
$settings = $settingCls | Get-ScsmObject @scsmMGMTParams
$maxAttach = $settings.MaxFileAttachmentsCount
$maxSize = $settings.MaxFileAttachmentSizeinKB
$prefix = $settings.ServiceRequestPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"System.WorkItem.ChangeRequest" {
$settingCls = Get-ScsmClass @scsmMGMTParams -Name "System.GlobalSetting.ChangeSettings$"
$settings = $settingCls | Get-ScsmObject @scsmMGMTParams
$maxAttach = $settings.MaxFileAttachmentsCount
$maxSize = $settings.MaxFileAttachmentSizeinKB
$prefix = $settings.SystemWorkItemChangeRequestIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"System.WorkItem.Problem" {
$settingCls = Get-ScsmClass @scsmMGMTParams -Name "System.GlobalSetting.ProblemSettings$"
$settings = $settingCls | Get-ScsmObject @scsmMGMTParams
$maxAttach = $settings.MaxFileAttachmentsCount
$maxSize = $settings.MaxFileAttachmentSizeinKB
$prefix = $settings.ProblemIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"System.WorkItem.Release" {
$settingCls = Get-ScsmClass @scsmMGMTParams -Name "System.GlobalSetting.ReleaseSettings$"
$settings = $settingCls | Get-ScsmObject @scsmMGMTParams
$maxAttach = $settings.MaxFileAttachmentsCount
$maxSize = $settings.MaxFileAttachmentSizeinKB
$prefix = $settings.SystemWorkItemReleaseRecordIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"System.WorkItem.Activity.ReviewActivity" {
$ActivitySettingsObj = Get-SCSMObject -Class (Get-SCSMClass -Name "System.GlobalSetting.ActivitySettings$" @scsmMGMTParams) @scsmMGMTParams
$prefix = $ActivitySettingsObj.SystemWorkItemActivityReviewActivityIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"System.WorkItem.Activity.ManualActivity" {
$ActivitySettingsObj = Get-SCSMObject -Class (Get-SCSMClass -Name "System.GlobalSetting.ActivitySettings$" @scsmMGMTParams) @scsmMGMTParams
$prefix = $ActivitySettingsObj.SystemWorkItemActivityManualActivityIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"System.WorkItem.Activity.ParallelActivity" {
$ActivitySettingsObj = Get-SCSMObject -Class (Get-SCSMClass -Name "System.GlobalSetting.ActivitySettings$" @scsmMGMTParams) @scsmMGMTParams
$prefix = $ActivitySettingsObj.SystemWorkItemActivityParallelActivityIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"System.WorkItem.Activity.SequentialActivity" {
$ActivitySettingsObj = Get-SCSMObject -Class (Get-SCSMClass -Name "System.GlobalSetting.ActivitySettings$" @scsmMGMTParams) @scsmMGMTParams
$prefix = $ActivitySettingsObj.SystemWorkItemActivitySequentialActivityIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"System.WorkItem.Activity.DependentActivity" {
$ActivitySettingsObj = Get-SCSMObject -Class (Get-SCSMClass -Name "System.GlobalSetting.ActivitySettings$" @scsmMGMTParams) @scsmMGMTParams
$prefix = $ActivitySettingsObj.SystemWorkItemActivityDependentActivityIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"Microsoft.SystemCenter.Orchestrator.RunbookAutomationActivity" {
$ActivitySettingsObj = Get-SCSMObject -Class (Get-SCSMClass -Name "System.GlobalSetting.ActivitySettings$" @scsmMGMTParams) @scsmMGMTParams
$prefix = $ActivitySettingsObj.MicrosoftSystemCenterOrchestratorRunbookAutomationActivityBaseIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"System.WorkItem.Activity.SMARunbookActivity" {
$ActivitySettingsObj = Get-SCSMObject -Class (Get-SCSMClass -Name "System.GlobalSetting.ActivitySettings$" @scsmMGMTParams) @scsmMGMTParams
$prefix = $ActivitySettingsObj.MicrosoftSystemCenterOrchestratorRunbookAutomationActivityBaseIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"Cireson.Powershell.Activity" {
$ActivitySettingsObj = Get-SCSMObject -Class (Get-SCSMClass -Name "System.GlobalSetting.ActivitySettings$" @scsmMGMTParams) @scsmMGMTParams
$prefix = $ActivitySettingsObj.SystemWorkItemActivityIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
"Cireson.Notification.Activity" {
$ActivitySettingsObj = Get-SCSMObject -Class (Get-SCSMClass -Name "System.GlobalSetting.ActivitySettings$" @scsmMGMTParams) @scsmMGMTParams
$prefix = $ActivitySettingsObj.MicrosoftSystemCenterOrchestratorRunbookAutomationActivityBaseIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
}
return @{"MaxAttachments"=$maxAttach;"MaxAttachmentSize"=$maxSize;"Prefix"=$prefix;"PrefixRegex"=$prefixRegex}
}
#----------------------------------------------------
#Function to set id prefix to activities in template
#----------------------------------------------------
function Update-SCSMPropertyCollection
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param (
[Microsoft.EnterpriseManagement.Configuration.ManagementPackObjectTemplateObject]$Object =$(throw "Please provide a valid template object"),
$Alias
)
if($PSCmdlet.ShouldProcess("$($Object.DisplayName)"))
{
#Regex - Find class from template object property between ! and ']
$pattern = '(?<=!)[^!]+?(?=''\])'
if (($Object.Path -match $pattern) -and (($Matches[0].StartsWith("System.WorkItem.Activity")) -or ($Matches[0].StartsWith("Microsoft.SystemCenter.Orchestrator")) -or ($Matches[0].StartsWith("Cireson.Powershell.Activity")) -or ($Matches[0].StartsWith("Cireson.Notification.Activity"))))
{
#Set prefix from activity class
$prefix = (Get-SCSMWorkItemSetting -WorkItemClass $Matches[0])["Prefix"]
#Create template property object
$propClass = [Microsoft.EnterpriseManagement.Configuration.ManagementPackObjectTemplateProperty]
$propObject = New-Object $propClass
#Add new item to property object
$propObject.Path = "`$Context/Property[Type='$alias!System.WorkItem']/Id$"
$propObject.MixedValue = "$prefix{0}"
#Add property to template
$Object.PropertyCollection.Add($propObject)
#recursively update activities in activities
if ($Object.ObjectCollection.Count -ne 0)
{
foreach ($obj in $Object.ObjectCollection)
{
Update-SCSMPropertyCollection -Object $obj -Alias $alias
Write-host "$PRefix --- $Object --- $Alias"
}
}
}
}
}
#----------------------------------------------------
#Function to apply template after it has been updated
#----------------------------------------------------
function Apply-SCSMTemplate
{
Param ([Microsoft.EnterpriseManagement.Common.EnterpriseManagementObjectProjection]$Projection =$(throw "Please provide a valid projection object"),
[Microsoft.EnterpriseManagement.Configuration.ManagementPackObjectTemplate]$Template = $(throw 'Please provide an template object, ex. -template template'))
#Get alias from system.workitem.library managementpack to set id property
$templateMP = $Template.GetManagementPack()
$alias = $templateMP.References.GetAlias((Get-SCSMManagementPack system.workitem.library))
#Update Activities in template
foreach ($TemplateObject in $Template.ObjectCollection)
{
Update-SCSMPropertyCollection -Object $TemplateObject -Alias $Alias
}
#Apply update template
Set-SCSMObjectTemplate -Projection $Projection -Template $Template -ErrorAction Stop @scsmMGMTParams
Write-Host "Successfully applied template:`n"$template.DisplayName "`nTo:`n"$Projection.Object
}
#--------------------------------
#INITIALIZE
#--------------------------------
$SMDefaultComputer = $ComputerName
#Load SMlets module
if (!(Get-Module smlets)) {Import-Module smlets -force -ErrorAction stop}
#Get object from guid
$emo = get-scsmobject -id $id
#determine projection according to workitem type
switch ($emo.GetLeastDerivedNonAbstractClass().Name)
{
"System.workitem.Incident" {$projName = "System.WorkItem.Incident.ProjectionType" }
"System.workitem.ServiceRequest" {$projName = "System.WorkItem.ServiceRequestProjection"}
"System.workitem.ChangeRequest" {$projName = "System.WorkItem.ChangeRequestProjection"}
"System.workitem.Problem" {$projName = "System.WorkItem.Problem.ProjectionType"}
"System.workitem.ReleaseRecord" {$projName = "System.WorkItem.ReleaseRecordProjection"}
default {throw "$emo is not a supported workitem type"}
}
#Get object projection
$emoID = $emo.id
$WIproj = Get-SCSMObjectProjection -ProjectionName $projName -Filter "Id -eq $emoID"
#Get template from displayname or id
if ($TemplateDisplayName)
{
$template = Get-SCSMObjectTemplate -DisplayName $TemplateDisplayName
}
elseif ($templateId)
{
$template = Get-SCSMObjectTemplate -id $TemplateId
}
else
{
throw "Please provide either a template id or a template displayname to apply"
}
#Execute apply-template function if id and 1 template exists
if (@($template).count -eq 1)
{
if ($WIProj)
{
Apply-SCSMTemplate -Projection $WIproj -Template $template
}
else
{throw "Id $Id cannot be found";}
}
else{throw "Template cannot be found or there was more than one result"}
the exchange connector doesn't account for Cireson notification activities.
Yeah...it doesn't. I can create a pull request for this, but I'm certainly open to receiving/co-authoring one if it were to be created on the repo 😁
I've never actually done that before with github, but the changes are fairly minimal and straight forward
Added this to function Get-SCSMWorkItemSetting
"Cireson.Notification.Activity" {
$ActivitySettingsObj = Get-SCSMObject -Class (Get-SCSMClass -Name "System.GlobalSetting.ActivitySettings$" @scsmMGMTParams) @scsmMGMTParams
$prefix = $ActivitySettingsObj.MicrosoftSystemCenterOrchestratorRunbookAutomationActivityBaseIdPrefix
$prefixRegex = ""
foreach ($char in $prefix.tochararray()) {$prefixRegex += "[" + $char + "]"}
}
And made this change to the if block of function Update-SCSMPropertyCollection
if (($Object.Path -match $pattern) -and (($Matches[0].StartsWith("System.WorkItem.Activity")) -or ($Matches[0].StartsWith("Microsoft.SystemCenter.Orchestrator")) -or ($Matches[0].StartsWith("Cireson.Powershell.Activity")) -or ($Matches[0].StartsWith("Cireson.Notification.Activity"))))
That should be all you need for the exchange connector, the rest of my work was minor tweaks to make both scripts work with each other, and to make it work with the powershell activity correctly.
I'd be happy to learn how to do coauthoring or sending you the update through github if that is the preference.
@Bryan_Lalor I forgot Adam's function has much more functionality in it, sorry.
Here is our function we use to apply a template to a newly created SR:
It is much shorter and out of the exchange connector imo much of the functionality of Adam's function is not needed, e.g. the MaxAttachement Size. And the "Default" path in the switch-case clause makes sure, that every activity, which is not stated directly, gets the AC prefix.
The only problem we have with that function is this: Let's say we have a reviewer(AD User object) added to an RA inside this template. If that user changes his/her distinguishedname, or even worse, a new user object is created because the user changes his/her username, and as soon a template with this Review activity is applied to the Service Request, the existing user object gets changed. For us the Distinguishedname got changed inside the AD User object, and the cachebuilder changed the user to IsAnalyst=0.
@Adam_Dzyacky have you experienced that issue as well?
@Simon_Zeinhofer I appreciate it, and no worries. I just got the script running, there are a few vestigial parts of the code to cleanup. Your code is also not considering cireson notification or powershell activities if you want to crib from mine to add that in.
Also have you considered using the user guid to find the user for your review activities instead of the DN? that will not change even if the DN is changed.
Cheers and thank you!
@Bryan_Lalor :
The
in the
will set the prefix for every activity type not explicitly mentioned to "AC", so there is no need to add any Cireson Activity directly (except the cloud Activity, as it has the SCO Activity prefix)
Ah, I overlooked that.
To your question with the reviewer: The reviewer is added automatically when the template is applied.
If you are not using emailed approvals you can apply a distribution list or mail enabled security group, instead of a user for assignment. That would avoid the issue and it still tracks who did the approval.