System Center Orchestrator - How to use a complex type and/or collection on the databus when using the “Run VMM PowerShell Script” activity from the Virtual Machine Manager Integration Pack
I’ve been working a lot of Cloud engagements lately focusing on extensive automation of service requests and custom automations to meet customers needs. Since we are using System Center Virtual Machine Manager to manage all the hypervisors I was doing a ton of PowerShell scripting to do my automations and that’s when I came across a road block when using the Run VMM PowerShell Script activity in System Center Orchestrator to pass data along the Orchestrator databus. What I was trying to do was something I’ve done all the time using the “Run .Net Script” activity, which was gather a collection and then publish it onto the Orchestrator databus for use in downstream activities. When I would do this using the Run VMM PowerShell Script activity I would get the following output of System.Object[] and ultimately my whole Orchestrator workflow would fail because my downstream activities are expecting certain string data that never gets published. For example take the PowerShell code example below.
$myPublishedVMs = @()
$myVMs = Get-SCVirtualMachine
ForEach ($vm in $myVMs)
{
$myPublishedVMs += $vm.Name.ToString()
}
If you build a simple Orchestrator runbook using the Run VMM PowerShell Script activity using the PowerShell code and publishing the $myPublishedVMs as Output Variable 01 and send it to a Send Platform Event for testing, you would expect the Send Platform Event to run as many times as the number of elements in the collection.
But instead what you get is an output of System.Object[] in the details of the Send Platform Event as shown below.
I immediately thought there was an issue until I started doing some digging, like reading the documentation :-), and there it was on the TechNet page saying that this is expected behavior for the Run VMM PowerShell Script activity if your “variable contains a complex type or a collection of objects”.
https://technet.microsoft.com/en-us/library/hh830716.aspx
Now knowing that I cannot use the Run VMM PowerShell Script activity to publish a collection out to the Orchestrator databus, I had to come up with a solution to make my runbooks work with all that rich data I was getting from the Run VMM PowerShell Script. At first thought I figured I would just substitute in my workflows the Run VMM PowerShell Script activity to the Run .Net Script activity. There’s pros and cons with this and I personally like the Run VMM PowerShell Script activity because it takes care of remoting to the VMM server and the importing of the VMM PowerShell module. When using the Run .Net Script activity I’ve found you have to instrument more error handling to account for the Invoke-Command and other things.
So understanding that I could pass a string as a variable, I figured I would do something I have done countless times in C#, which is to use the String Builder class and just append my string data to a string that I would just publish on the Orchestrator databus and on the next activity I would take the string and then do a split on it to get the items in a collection and then publish that collection onto the databus outside of using the Run VMM PowerShell script. It does add an extra step to your workflow, but the benefits of being able to utilize the built-in looping functionality of Orchestrator is well worth it. In using the same PowerShell code example you would make the following edits below.
$myPublishedVMs = new-object System.Text.StringBuilder
$myVMs = Get-SCVirtualMachine
ForEach ($vm in $myVMs)
{
$myPublishedVMs.append($vm.Name.ToString())
$myPublishedVMs.append(',')
}
$outputVariable01 = $myPublishedVMs.ToString()
Notice that I’m appending a comma as well and simply building a string that will look like “Server01,Server02,Server03,”. You can now output this string on the Orchestrator databus and use a split on the comma to create an array. One other thing that you want to be cautious of is the length of your string that you will put on the Orchestrator databus. Reading Robert Hearn’s blog post ( https://blogs.technet.com/b/orchestrator/archive/2012/05/08/orchestrator-quick-tip-what-s-the-maximum-size-of-parameters.aspx) I would keep the character length of this string to under 2000 characters. So the final code will look like this below.
$myPublishedVMs = new-object System.Text.StringBuilder
$myVMs = Get-SCVirtualMachine
ForEach ($vm in $myVMs)
{
$myPublishedVMs.append($vm.Name.ToString())
$myPublishedVMs.append(',')
}
$outputVariable01 = $myPublishedVMs.ToString()
$charCount = ($outputVariable01 | Measure-Object –Character).Characters
If ($charCount –gt 2000)
{
Throw [System.Exception]”The output string is more than 2000 characters.”
}
In the following activity use the Run .Net Script activity to convert the $myPublishedVMs string into a collection object that you can then publish back to the Orchestrator databus. One thing to note is that the way I’m building my string in the Run VMM PowerShell Script will always leave an empty element do to the final append of a comma. I’m filtering out the empty element by simply checking if it is null or empty. That PowerShell script code will look similar to this below.
$myVMsArray = @()
$stringOutput = “<Output Variable 01 from Run VMM PowerShell Script>”
$splitVMsOnComma = $stringOutput.Split(“,”)
ForEach ($vm in $splitVMsOnComma)
{
If (![string]::IsNullOrEmpty($vm))
{
$myVMsArray += ,$vm
}
}
$myVMsArray
The final test Orchestrator runbook will look like the following.
Notice there are double quotes around the Output Variable 01
Once you check the Orchestrator runbook in and run it, you should see the following results.
On my Events tab I show two entries from the Send Platform Event and this correlates to what I have in my current lab, which is two virtual machines showing in Virtual Machine Manager.
And if I look at both of those events listed in Orchestrator I should see each individual virtual machine listed as an event, which I do shown below.
So that’s all for this post. I hope you guys out there managing and developing solutions around Clouds can utilize this. I know for me being able to have this functionality was HUGE when working with Virtual Machine Manager and developing service requests. This can be very powerful when using the Run VMM PowerShell Script because that activity allows for up to 20 outputs on the Orchestrator databus. Have fun out there :-).
Thanks,
Phil Gibson [MSFT]
Comments
- Anonymous
August 12, 2015
I just came across this now, two years after its publication, and this is exactly what I needed to know! We are heavily automating our HyperV VM deployments to allow restricted-access developers a sandbox cloud to deploy from templates any server they want/need to test on. And we incorporate Orchestrator heavily in the management of stale servers they no longer use. I had a PowerShell script that grabbed all the host names matching the correct prefix "HVSQL*" for example and tried to pass that into a runbook for a mass delete, and could not for the life of me understand why the outvariable only ever passed along a single hostname. I had no clue of the limitations of the Orchestrator Data Bus. Thanks Phil!
PS. Are they ever going to patch this in an UR to allow native complex variable passing?