sabell2012
Mega Sage
Mega Sage

NOTE: MY POSTINGS REFLECT MY OWN VIEWS AND DO NOT NECESSARILY REPRESENT THE VIEWS OF MY EMPLOYER, ACCENTURE.

 

DIFFICULTY LEVEL: ADVANCED
Assumes having taken the class SSNF and has good advanced level of knowledge and/or familiarity with Scripting in ServiceNow. Assumes good knowledge and/or familiarity of Orchestration, Workflows, and Scripting in ServiceNow.


Originally Orchestration contained a baseline Run PowerShell Activity. Unfortunately this was deprecated in way back in the Helsinki release Patch 1. With this article I show how you can bring back that functionality using Orchestration's Custom Activity Builder.

 

I will also introduce a couple of best practices I use when creating Custom Workflow Activities:

1. Post-Processing boiler plate scripts

2. Custom Activity Script Includes

 

 

Pre-Requisites

 

TIP: We will build this example Globally scoped. If you want to put this into the actual baseline PowerShell folder then you will need to change the application scope to PowerShell, create the new Custom Activity, and clear out the Category. The new activity will then appear in the PowerShell folder, and you can still use it in your Globally scoped workflows.

 

TIP: You might want to create an update set to capture your work. You can click on the Publish button on the new Custom Activity and the Test Workflow to save your work in the update set.

 

 

Lab 1.1: Script Include Library

1. The first step is to create a Script Include library to support our new Custom Activity. This is a best practice with the following benefits:

- Maintainability: The code is centralized into a single location for easy searchability, and only needs modification in a single location.

- Reusability: Creation of a script function library promotes reusability, and reduces time-to-completion.

- Generic code base:  Promotes greater reuse, and data driven scripting. The script can be used by a wider variety of calling functions. Think Swiss-Knife!

2. Navigate to System Definition > Script Includes.

3. Click on the New button.

4. Fill in the form with the following:

Name: ML_WorkflowActivityUtils (ML stands for Mini-Lab 😁)

Accessible from: All application scopes.

Description: Workflow Custom Activity utility functions

Script

 

var location = 'SI:' + this.type;

var ML_WorkflowActivityUtils = Class.create();
ML_WorkflowActivityUtils.prototype = {
    initialize: function (location) {
        this.location = location;
    },

    // method to handle the post process results of a Custom Activity
    postProcessing: function (executionResult, activityOutput) {
        if (gs.nil(executionResult.error)) {
            // initialize our result variable
            activityOutput.result = "success";
            try {
                var output = executionResult.output;
                // if our output returned information then capture it
                if (output != null) {
                    activityOutput.output = output.substring(output.indexOf('<Objects>'));
                    gs.info('---> [{1}] activityOutput.output: {0}',
                        [activityOutput.output, this.location + '.postProcessing']);
                }
            } catch (err) {
                gs.error('---> [{1}] ERROR: {0}', [err, this.location + '.postProcessing']);
            }
        } else {
            // we had something bad happen, handle it!
            activityOutput.result = "failure";
            activityOutput.errorMessage = executionResult.errorMessages;
            gs.info('---> [{1}] activityOutput.errorMessage: {0}',
                [activityOutput.errorMessage, this.location + '.postProcessing']);
        }
    },

    type: 'ML_WorkflowActivityUtils'
};

 

5. Click on the Submit button to save your work.

 

Lab 1.2: Custom Workflow Activioty

1. In your instance navigate to Orchestration > Workflow Editor, and open the Workflow Editor

2. In the Workflow Editor navigate to the Custom tab, and click the plus ("+") button to create a new Activity.

3. Choose the Powershell Template from the menu. This will display the Activity Designer with the template form.

 

sabell2012_0-1703874570038.png

 

4. Fill out the form with the following:

Name: PowerShell Command

Short Description: Execute a PowerShell Command

Accessible from: All application scopes

Category: PowerShell

Description: Activity to run a custom PowerShell

 

sabell2012_1-1703875064115.png

 

5. Click on the Continue button.

6. On the Inputs form Add three fields

Name: Hostname, Type: String

Name: Command, Type: String

Name: Credential, Type: String

 

sabell2012_2-1703875153787.png

 

7. Click on the Continue button.

8. Fill in the form with the following:

Target Host: drag the Hostname input to this field

Script Type: Custom PowerShell command

Command: drag the Command input to this field

Credential tag: drag the Credential input to this field

 

sabell2012_3-1703875277514.png

 

9. Click the Continue button.

10. Add three Output fields (from this point forward the creation of the new activity will be the same as in my previous article).

Name: result, Type: String

Name: output, Type: String

Name: errorMessage, Type: String

 

sabell2012_4-1703875393808.png

 

11. Click on the Go to Post-Processing button.

12. Fill in the Post-Processing form with the following:

Output process script:

 

var location = 'WFCA: PowerShell Command';
new ML_WorkflowActivityUtils(location).postProcessing(executionResult, activityOutput);

 

sabell2012_5-1703875594987.png

 

13. Click the Continue button.

14. Add two condition fields:

Name: Success

Condition: activityOutput.result == 'success'

Else: false

Order: 100

Name: Failure

Condition: leave blank

Else: true

Order: 200

 

sabell2012_6-1703875685266.png

 

15. Now click on the Save button to save your work.

 

 

Test the Workflow

Now we are ready to actually test our new Custom Activity!

 

1. In the Workflow Editor navigate to Custom > Global > PowerShell. You will now see your new PowerShell Command Activity present.

 

sabell2012_7-1703875870667.png

 

2. Navigate to the Workflows tab, and click the plus "+" button to create a new workflow.

3. Fill in the New Workflow form with the following:

Name: PowerShell Command Workflow

Table: Global

Description: Testing the PowerShell Command Custom Activity

If condition matches: -- None –

4. Click the Submit button to start building your workflow.

5. Drag your custom PowerShell Command Activity onto the new workflow and fill in the properties form with the following:

Name: PowerShell Command Test

Hostname: 127.0.0.1

Command: dir

 

sabell2012_8-1703876008568.png

 

6. Click the Submit button to save the activity to the workflow.

7. To hang onto our results for the Custom Activity we will need to add a Run Script Activity after the PowerShell Command; in the Success branch. The after-activity results from your Custom Activity are available for coding in the Data tab, and might have a different number. The number is based on when the activity was put onto the canvas and represents the order in which it was placed on the canvas.  So a "3" means it was the third activity placed on the canvas.

 

sabell2012_9-1703876093257.png

 

NOTE: It is important to understand that workflow.scratchpad (and other workflow variables) are not available inside the Custom Activity! They can only be passed around through activity parameters.

 

8. Navigate to Core tab > Utilities and drag out a Run Script Activity onto the Success output line of your custom activity.

9. Fill in the properties form with the following:

Name: Handle Results

Script:

 

var location = 'WF:' + context.name + '.' + activity.name;
var psCommandTest = data.get(3);

gs.info('---> [{1}:{2}] previous_activity.result: {0}', 
		[psCommandTest.result, new GlideDateTime().getNumericValue(), location]);    
gs.info('---> [{1}:{2}] previous_activity.output: {0}', 
		[psCommandTest.output, new GlideDateTime().getNumericValue(), location]);    
    
// package up the results for pushing onto the workflow (future use)
var results = {output : '', error : ''};    
results.output = psCommandTest.output;    
results.error = psCommandTest.errorMessage;    
workflow.info('---> [{1}:{2}] {0}', 
	[results.output, new GlideDateTime().getNumericValue(),location]);    
workflow.scratchpad.output = results; // pass the results out onto the data stream

 

10. Click the Submit button to save your Activity to the workflow.

 

sabell2012_1-1703876621304.png

 

NOTE: The "data.get(3)" numeric value must match your Activity Outputs numeric value!


11. Add another Run Script Activity into the Failure output of the Run PowerShell Script Test activity.

Best Practice: You should always handle potential errors!

12. Fill out the form with the following:

Name: Handle Failure

Script:

 

var location = 'WF:' + context.name + '.' + activity.name;
var psCommandTest = data.get(3);

try {
	gs.info('---> [{1}:{2}] previous_activity.result: {0}', 
		[psCommandTest.result, new GlideDateTime().getNumericValue(), location]);    
	gs.info('---> [{1}:{2}] previous_activity.output: {0}', 
		[psCommandTest.output, new GlideDateTime().getNumericValue(), location]);    
	gs.error('---> [{1}:{2}] previous_activity.errorMessage: {0}', 
		[psCommandTest.errorMessage, new GlideDateTime().getNumericValue(), location]);    

	// package up the results for pushing onto the workflow (future use)
	var results = {output : '', error : ''};    
	results.output = psCommandTest.output;    
	results.error = psCommandTest.errorMessage;    
	workflow.info('---> [{1}:{2}] {0}', 
		[results.output, new GlideDateTime().getNumericValue(),location]);    
	workflow.scratchpad.output = results; // pass the results out onto the data stream
}
catch(err) {
	gs.error('---> [{1}:{2}]\n{0}', 
		[err, new GlideDateTime().getNumericValue(),location]);
}

 

 

 

13. Wire up the workflow to match the following diagram:

 

sabell2012_2-1703876800357.png

 

14. Run the workflow.

15. You should have a successful run that looks like this:

 

sabell2012_3-1703876874217.png

 

16. From you instance navigate to System Logs > System Log > All. The System Logs list view will be displayed.

17. Filter for messages starting with "--->", and order by Created descending. You should see an entry similar to the following:

 

sabell2012_4-1703876913101.png

 

TIP: Notice the millisecond times in the messages. This can help you know exactly when something was run and in what order (the Created column only goes to the second).

 

SAD NOTE: Currently developers are not allowed to modify existing or to create their own Custom Activity templates.

 

SECOND SAD NOTE: You are limited to String, Integer, Boolean, Decimal, Object, Array, and Encrypted for Custom Activity input variable types. Choice and Reference fields are not unfortunately not available.

 

COOL NOTE: Notice that if you want to modify your Custom Activity script you don't have to get into the Workflow Editor/Custom Activity Editor to do so, you just have edit the Script Include! Thus the beauty of Script Includes.

 

And there you go! You have created your first generic PowerShell Custom Activity! 

 

Enjoy!

Steven Bell.

 

If you find this article helps you, don't forget to log in and mark it as "Helpful"!

 

sabell2012_0-1702752346156.png


Originally published on: 08-22-2018 7:32 AM

I updated the code, fixed broken links, and brought the article into alignment with my new formatting standard.

Comments
Irek1
Giga Contributor

I basically followed it with SSH instead  PowerShell and 'ls' command instead 'dir' and it worked just fine on Linux MID server

sabell2012
Mega Sage
Mega Sage

Excellent, thanks for checking it out for SSH!

Version history
Last update:
‎12-29-2023 11:10 AM
Updated by:
Contributors