Workflow that Triggers on Relationship Add or Remove

It’s easy to create workflows that trigger on property changes such as when the status of an Incident changes from Active to Resolved.  However, you can’t use the console or Authoring tool to configure workflows that have criteria for relationship changes.

Fortunately with a bit of XML tweaking it is possible to trigger a workflow when a relationship is created or when it is deleted.

This method will work with email subscriptions, console workflows or authored workflows created using the Authoring tool.

In this example I’ve used the Authoring tool to create a workflow that generates an event in the Operations Manager Event Log when the Affected User is set on an Incident.

Regardless of your method it is important to ensure you set some kind of criteria (doesn’t really matter what you choose) as that makes the XML easier to edit.  I’ve used a criteria based on the Affected User Company property.

I’ve then configured the rest of the workflow the way I want it and saved my configuration.

Next I edit the unsealed management pack.  To do this for an email subscription or a console workflow, export the management pack first.

The rest of the configuration will be done by editing the management pack using an XML editor.  The section I want is the subscription which is located in the Rule under the Rules section.

<Subscription>
  <WindowsWorkflowConfiguration>
    <AssemblyName>DevTestIncidentWorkflows</AssemblyName>
    <WorkflowTypeName>WorkflowAuthoring.DevTestIncidentWorkflows</WorkflowTypeName>
    <WorkflowParameters></WorkflowParameters>
    <RetryExceptions></RetryExceptions>
    <RetryDelaySeconds>60</RetryDelaySeconds>
    <MaximumRunningTimeSeconds>300</MaximumRunningTimeSeconds>
  </WindowsWorkflowConfiguration>
</Subscription>

I can see the conditions in the subscription.  I need to replace the subscription with my relationship subscription in order to set the criteria to be when a relationship is created between an Incident and the Affected User.

<RelationshipSubscription RelType="$MPElement[Name='System_WorkItem_Library!System.WorkItemAffectedUser']$" SourceType="$MPElement[Name='System_WorkItem_Library!System.WorkItem']$" TargetType="$MPElement[Name='System!System.User']$">
  <AddRelationship>
  </AddRelationship>
</RelationshipSubscription>

The key difference here is that we are using a RelationshipSubscription.  The relationship is made up of the relationship property, the target and the source.  The properties you need can be found by looking at class properties using the Authoring tool, or by using PowerShell.  For example:

$Class = Get-SCSMClass | where {$_.DisplayName -eq 'Incident'}
$Class.PropertyCollection | format-table DisplayName,Name,Type

Lets break the relationship down.  The first part identifies the relationship.

Name='System_WorkItem_Library!System.WorkItemAffectedUser'

This tells the workflow to use the System.WorkItemAffectedUser relationship that can be found in the System_WorkItem_Library management pack.  System_WorkItem_Library must match the name of the reference at the beginning of this management pack.  E.G:

<Reference Alias="System_WorkItem_Library">
  <ID>System.WorkItem.Library</ID>
  <Version>7.5.3079.0</Version>
  <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
</Reference>

The second part identifies the source class.

Name='System_WorkItem_Library!System.WorkItem'

In this case the source class is System.WorkItem.  Hang on… aren’t we supposed to be using the Incident class?  Well, the Incident class is derived from the abstract class Trouble Ticket, which, in turn is derived from the Abstact class Work Item.  This means the relationship from Work Item is also present in Incident.

More information on Abstract classes can be found here.

The third and final part of the relationhip is the target class.

Name='System!System.User'

Again, although we want to use the Active Directory User class, we really want the base class that the relationship is derived from.  This is the User class.

So my new subscription should look like this:

<DataSources>
  <DataSource ID="DS" TypeID="SystemCenter1!Microsoft.SystemCenter.CmdbInstanceSubscription.DataSourceModule">
    <Subscription>
      <RelationshipSubscription RelType="$MPElement[Name='System_WorkItem_Library!System.WorkItemAffectedUser']$" SourceType="$MPElement[Name='System_WorkItem_Library!System.WorkItem']$" TargetType="$MPElement[Name='System!System.User']$">
         <AddRelationship>
        </AddRelationship>
      </RelationshipSubscription>
      <PollingIntervalInSeconds>60</PollingIntervalInSeconds>
      <BatchSize>100</BatchSize>
    </Subscription>
  </DataSource>
</DataSources>

If I wanted the workflow to trigger when the relationship is deleted between an Incident and the Affected User I would use this type of subscription instead:

<DataSources>
  <DataSource ID="DS" TypeID="SystemCenter1!Microsoft.SystemCenter.CmdbInstanceSubscription.DataSourceModule">
    <Subscription>
      <RelationshipSubscription RelType="$MPElement[Name='System_WorkItem_Library!System.WorkItemAffectedUser']$" SourceType="$MPElement[Name='System_WorkItem_Library!System.WorkItem']$" TargetType="$MPElement[Name='System!System.User']$">
        <DeleteRelationship>
        </DeleteRelationship>
      </RelationshipSubscription>
      <PollingIntervalInSeconds>60</PollingIntervalInSeconds>
      <BatchSize>100</BatchSize>
    </Subscription>
  </DataSource>
</DataSources>

Script – Automatically Creating a Customer Organisation if it Doesn’t Exist

In a previous blog post I created a PowerShell script that would automatically populate the relationship property for the Customer Organisation class when an Incident is created.

A PowerShell snippet below can be plugged into the original PowerShell script that will automatically create the Customer Organisation if it doesn’t already exist.

# If no match between the user and the Customer Organisation is found then create the Customer Organisation CI and then create the relationship
 if ($CO -eq $null)

  {

   # Get the class for Customer Organisation
   $COClass = Get-SCSMClass -Name "CustomerOrganisation"

   # Define the properties that will populate the class instance
   $Properties = @{DisplayName = "$AU.Company"}

   # Create the class instance
   $COCI = New-SCSMClassInstance -Class (Get-SCSMClass -Name $COClass) -property $Properties

   #Create the relationship between the Incident and the new Customer Organisation CI
   New-SCRelationshipInstance -RelationshipClass $COREL -Source $COCI -Target $IR

  }

It uses an If statement, however in the original script there is already an If statement that looks for the CO null value, so if you do plug it in, it may be more efficient to use an Else statement instead.

Happy scripting!

Automatically Adding the Customer Company CI When an Incident is Created – Workflow Authoring – Part 2 Authoring the Workflow

Automatically Adding the Customer Company CI When an Incident is Created – Workflow Authoring – Part 1 Constructing the PowerShell Script

Automatically Adding the Customer Company CI When an Incident is Created – Workflow Authoring – Part 2 Authoring the Workflow

In part 1 we defined a PowerShell script for automatically obtaining the IR and the Customer Organisation CI based on the Company property of the Affected User.  In part 2 we will plug that script into a workflow.

Creating the Workflow

New MP

First thing you need to do is create a new management pack to contain your workflow.  I’m a big fan of separating out Classes, Forms, and Workflows into separate management packs, and group them together. Indeed it is best practice to place your forms into separate management packs from your classes. This approach can make it easier to decommissioned a feature at a later date, as importing an updated MP that has had a class, form, or workflow deleted from it is not supported.

 New Workflow

Now Create a new Workflow called something like “UpdateIRwithCustomerOrganisation”

Give it a name and a description:

posts-scsmauthwfdemo01

Set the condition.  In this case we need it to run on an ‘as required’ basis.

posts-scsmauthwfdemo02

Finally select the class and criteria.  We want our workflow to trigger when an Incident is created.

posts-scsmauthwfdemo03

You should finish up with an empty workflow in your Management Pack.

posts-scsmauthwfdemo09

Next you’ll need to drag out a PowerShell script activity from the Toolbox.  For this demo we only need one script activity.  Give the script activity a more user friendly name.  In this case I’ve used “PowerShellUpdateIRwCustOrg”.  You can’t add spaces in the activity name using the Authoring Tool, usually I would edit the XML to do this, but for the purposes of this post I’ve left it as is.

posts-scsmauthwfdemo08

Now we need to configure the parameters and body of the script.  To do this click on the radial button next to “Script Body”.

First lets setup a variable for the IR.  Give it a name without using the $ character.  In this case I’m using IRID.  Then select the ID property of the Incident class using the radial button.  When you’ve finished it should look like this:

posts-scsmauthwfdemo07

Now onto the PowerShell script itself.  This is a simple case of writing or pasting in your script into the Script Body of the PowerShell Activity.

posts-scsmauthwfdemo06

N.B. You can see that the first line of the script in the body is to load the SCSM PowerShell cmdlets.  Some of you may be asking why I’m not specifying it in Script Properties of the PowerShell Activity – simply because it’s not supported for this module.

You’re All Set!

Now all you need to do is seal your workflow Management Pack and import it (including the Customer Organisation if you’ve been following along).

When your Incidents are created the Customer Organisation CI relationship will automatically be populated!  Happy automating!