Adding an Options Menu Configuration to Custom Activities

Adding an Options Menu Configuration to Custom Activities

  • Comments 1
  • Likes

Yesterday, I wrote about how to debug a custom activity using Visual Studio. Today I’m going to show you how to add an item to the Options Menu so that you can have a reusable configuration setting that can be used across multiple activities in an IP. This is typically used for configuring connection settings or other things that are common across multiple activities and you don’t want to have to enter it over and over again for each activity.

The cool thing about using an options menu configuration is that you can use it for a single-level cascading dependency action. For example, you can change inputs, outputs or even the major functions of the activity based on the selection the user makes for the configuration. In this example, I’ll show how to add an ActivityConfiguration item and use it to alter how the activity works. In the next article, I’ll show how to use it to alter inputs and outputs when using the imperative approach to creating activities.

Starting from the “Hello World” activity I showed yesterday (and in the SDK examples at http://orchestrator.codeplex.com), I created a new activity called “Hello World 2”. I also created a new class called “HelloWorldConfiguration”, shown below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Microsoft.SystemCenter.Orchestrator.Integration.Examples.HelloWorld2
{
    [ActivityData("Hello World Configuration")]
    public class HelloWorldConfiguration
    {
        private AlterationMethod _alterationType = AlterationMethod.None;

        public HelloWorldConfiguration()
        {
            AlterationType = AlterationMethod.None;
        }

        public HelloWorldConfiguration(AlterationMethod alterationType)
       ��{
            AlterationType = alterationType;
        }
            
        [ActivityInput]
        public AlterationMethod AlterationType
        {
            get { return _alterationType; }
            set { _alterationType = value; }
        }
    }

    public enum AlterationMethod
    {
        Reverse,
        Scramble,
        None
    };
    
}

This class defines a data structure that’s used to define the configuration options, and an enum to allow for user selection of values. Here’s how it works:

The ActivityData attribute is used to define a data structure which can be used as a configuration set for the activity (or multiple activities). In this class, you’ll define inputs for properties you want the user to be able to set. You can also define outputs so that the configuration info can be published on the databus. This example has one input, called “AlterationType” and uses the enum “AlterationMethod”. By specifying an enum, you’ll automatically get a pop-up selection box to select from the available choices in the enum.

Important: you always need to specify a default constructor for this class or you’ll get an exception in the Designer. When the activity loads and displays the properties page, it initializes this class using the default constructor.

By the way, you can specify multiple ActivityData classes to have multiple configuration types and use whichever ones you want in each activity in your IP.

Now that we have a configuration class defined, it needs to be added to the activities that will use it. Adding it to the activity is as simple as this:

[ActivityConfiguration]
public HelloWorldConfiguration Settings
{
    set
    {
        _settings = value;
    }
}
protected HelloWorldConfiguration _settings;

When the activity loads, it sees the ActivityConfiguration attribute and initializes the HelloWorldConfiguration class. Then, when the user chooses the option setting in the configuration, that data is available in the “Settings” property at design time and at runtime.

Here’s an example of using the value to modify activity behavior at runtime. When the user selects a value, “Reverse”, “Scramble” or “None”, this changes how the ActivityOutput is processed:


[ActivityOutput("Hello World Output")]
public string HWOutput
{
    get
    {
        if (_settings.AlterationType == AlterationMethod.Reverse)
        {
            char[] arr = hwinput.ToCharArray();
            Array.Reverse(arr);
            return new string(arr);
        }
        else if (_settings.AlterationType == AlterationMethod.Scramble)
        {
            return ScrambleString(hwinput);
        }
        return hwinput;
    }
}

In the code above, you can see that when the user selects “Reverse”, they get the original behavior of the activity, which is to reverse the string. When they choose “Scramble”, it branches to run another method to scramble the string. And, if they choose “None”, then nothing is done to the string and it returns the original value. Below is the ScrambleString method code:


    private string ScrambleString(string input)
    {
        char[] arr = new char[input.Length];
        Random rand = new Random(10000);
        int index = 0;

        while (input.Length > 0)
        {
            int next = rand.Next(0, input.Length - 1);
            arr[index] = input[next];
            input = input.Substring(0, next) + input.Substring(next + 1);
            ++index;
        }
        return new String(arr);
    }
}

When you compile the code, you can now use this configuration by selecting (in Runbook Designer) Options > Invoke .NET and then clicking Add and selecting the Assembly  and Class.

image

You can see that I have one option, named “AlterationType”. By the way, if I want a more friendly name than the actual property name, I can just specify that in the ActivityInput attribute just like any other input property.I can define multiple configurations using this type, like below:

image

Then I can use these configuration settings in the Invoke .NET activity like this:

image

And, when I click the button next to Setup, I get a selection list:

image

Now, when I enter a string in the activity and use the Runbook tester, I get different results depending on the selection in the Setup property. Obviously, you can get a lot more elaborate with your configurations and add many different properties, potentially add live queries to fill selection boxes, and more. There are a lot of potential uses for configurations. Most of the time, we just have one configuration type being used per IP, but you can see how you could have multiple configuration types – perhaps part of an IP uses PowerShell remoting and another part uses WMI. You’d want separate configuration settings for each of those, and only specific types would be available in different activities. Or, you could use the configuration setting as a way to alter the entire set of input or output properties based on what the user selects. More on that in the next article!

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Did you ever come out with the next article?  I liked this one and am ready for a deeper dive into creating custom configurations for my custom activities.