Powershell Library - How to
I have coded a PowerShell script to add 7 days to the end of every RA, MA, PA in a ticket but the script reports back: - I am asking for a how to add a powershell script to a ticket without the use of Orchestrator. But I want the script to affect the parent ticket that it is running against.
An error was written to the Error stream!
property
Value cannot be null.
Parameter name: criteria
script:
# Set param at bottom of Template param([guid]$parentId) # Import the module Import-Module SMLets # Ticket number as a parameter #$TicketNumber = "SR1058514" try { # Identify the current Service Request. This depends on your setup. $Ticket = Get-SCSMObject -Class (Get-SCSMClass -Name System.WorkItem.ServiceRequest$) -Filter"IsCurrent -eq $true" if ($Ticket-eq$null) { throw"No current Service Request found." } $TicketNumber = $Ticket.Id # Calculate the due date $DueDate = (Get-Date).AddDays(7).ToString('MM/dd/yyyy') # Get the ticket $Ticket = Get-SCSMObject -Class (Get-SCSMClass -Name System.WorkItem.ServiceRequest$) -Filter"Id -eq $TicketNumber" if ($Ticket-eq$null) { throw"Ticket with ID $TicketNumber not found." } # Mark the ticket as a testing workitem $Ticket | Set-SCSMObject -Property Status -Value "In progress" # Get all activities related to the ticket $AllActivities = Get-SCSMRelatedObject -SMObject $Ticket -Relationship (Get-SCSMRelationshipClass -Name System.WorkItemContainsActivity$) # Iterate through each activity foreach ($Activityin$AllActivities) { # Get the child activities of the current activity $ChildActivities = Get-SCSMRelatedObject -SMObject $Activity -Relationship (Get-SCSMRelationshipClass -Name System.WorkItemContainsActivity$) # If there are any child activities if ($ChildActivities) { # Iterate through each child activity and update the title and due date foreach ($ChildActivityin$ChildActivities) { # Get the current title $CurrentTitle = $ChildActivity.Title # Append the due date to the title $NewTitle = "$CurrentTitle - Due date: $DueDate" # Update the title and due date Set-SCSMObject -SMObject $ChildActivity -PropertyHashtable @{ Title = $NewTitle ScheduledEndDate = $DueDate } Write-Output"Updated child activity: $($ChildActivity.Id)" } } # Get the current title $CurrentTitle = $Activity.Title # Append the due date to the title $NewTitle = "$CurrentTitle - Due date: $DueDate" # Update the title and due date Set-SCSMObject -SMObject $Activity -PropertyHashtable @{ Title = $NewTitle ScheduledEndDate = $DueDate } Write-Output"Updated activity: $($Activity.Id)" } } catch { Write-Output$_.Exception.Message } # Remove the module Remove-Module SMLets
Best Answer
-
Simon_Zeinhofer Customer Ninja IT Monkey ✭✭✭✭
Hello @Ryan_Kelley ,
to be honest I don't understand what you want to achieve exactly. In the script you have the parentId, but you never use it. But then you use an iteration to iterate through every service request, which has property "isCurrent" set to true - is IsCurrent a property you added via a class extension?
So if you want to use this script in every Service Request from a certain template, there is no need to use the
$Ticket = Get-SCSMObject -Class $srClass -Filter "IsCurrent -eq $true"
For that you have the parentId parameter inside the script.
If you do not want to use Orchestrator I can recommend you the use of Powershell Activities. I currently rebuilt some of our Service Request Template Automation Acitivties from SCO with them. We reduced the running time of one of our most important Service Requests from ~ 20 Minutes to 3 with that.
I have rewritten your script, so it should work when you use it in one of these Powershell Activities, which you can then add as first activity in your SR template. But at first I wanna give you some tips when writing your own powershell scripts:
- If you have to use a certain SCSM Class/Relationship Class more than once, I recommend defining the class in a variable at the top of your script and then using that variable when you need it. e.g.: $srClass = Get-SCSMClass -Name "System.WorkItem.ServiceRequest$" . Same goes for Relationship Classes: $containsActivity = Get-SCSMRelationshipClass -Name "System.WorkItemContainsActivity$"
- I copied your script inside an ISE and there were some errors immediately. You forgot to add some whitespaces, e.g. in "(foreach... in ...)" - this will lead to erros when it is running for sure.
- When getting all activities from a service request, there is no need to call the get-scsmrelatedobject again and again. If you add the -deth recursive parameter at the end, it will return all activities, no matter how nested they are.
- When updating the title of any workitem(be it IR,SR, Activities...) via script, always change the DisplayName as well. Else, it will remain the same as before. And then you have e.g. Title "Resolve SR - Due 07/20/2023" and DisplayName "MA 12345: Resolve SR".
The error you mentioned means, that the property, which you used for filtering, does not exist. I cannot reproduce it, as we do not have the property "IsCurrent" in our SR class in our system - But maybe you added it via a class extension.
So this is the script which should fit for the powershell activity, which you can then add as first activity in your template:
param([guid]$parentId) if(-not(Get-Module Smlets)) { Import-Module SMLets } $containsActivity = Get-SCSMRelationshipClass -Name "System.WorkItemContainsActivity$" $Ticket = Get-SCSMObject -Id $parentId # Calculate the due date $DueDate = (Get-Date).AddDays(7).ToString('MM/dd/yyyy') # Get all activities related to the ticket $AllActivities = Get-SCSMRelatedObject -SMObject $Ticket -Relationship $containsActivity -Depth Recursive foreach($activity in $AllActivities) { if(($activity.Id -like 'MA*') -or ($activity.Id -like 'PA*') -or ($activity.Id -like 'RA*')) { $CurrentTitle = $activity.Title $CurrentDisplayName = $activity.DisplayName $NewTitle = "$CurrentTitle - Due date: $DueDate" $NewDisplayName = "$CurrentDisplayName - Due date: $DueDate" Set-SCSMObject -SMObject $activity -PropertyHashtable @{Title = $NewTitle;DisplayName = $CurrentDisplayName;ScheduledEndDate = $DueDate} -PassThru Write-Output "Updated child activity: $($activity.Id)" } }
0
Answers
Hello @Ryan_Kelley ,
to be honest I don't understand what you want to achieve exactly. In the script you have the parentId, but you never use it. But then you use an iteration to iterate through every service request, which has property "isCurrent" set to true - is IsCurrent a property you added via a class extension?
So if you want to use this script in every Service Request from a certain template, there is no need to use the
For that you have the parentId parameter inside the script.
If you do not want to use Orchestrator I can recommend you the use of Powershell Activities. I currently rebuilt some of our Service Request Template Automation Acitivties from SCO with them. We reduced the running time of one of our most important Service Requests from ~ 20 Minutes to 3 with that.
I have rewritten your script, so it should work when you use it in one of these Powershell Activities, which you can then add as first activity in your SR template. But at first I wanna give you some tips when writing your own powershell scripts:
The error you mentioned means, that the property, which you used for filtering, does not exist. I cannot reproduce it, as we do not have the property "IsCurrent" in our SR class in our system - But maybe you added it via a class extension.
So this is the script which should fit for the powershell activity, which you can then add as first activity in your template:
Thank you for your in depth explanation! This resolved my issue and tought me more how to run powershell within scsm!
@Ryan_Kelley Glad I could help :)
I saw I made a mistake here:
Ofc, it has to be