Configuration Manager SP1 PowerShell in Orchestrator Part 2: The Rest of the Story

Well I thought I was Mr. Smarty Pants and had the whole ‘running 2012 Configuration Manager cmdlets from an Orchestrator Run .Net Script activity’ figured out (as documented in this post). As it turns out, there is bit more to the story. Everything documented in the initial post is valid, however as I found out today there is an additional step that needs to be taken in order to load data from the executed Configuration Manager PowerShell CMDLETS onto the Orchestrator data bus. So let’s just consider this post two in the series.

In this post I will be detailing the steps needed in order to load a Configuration Manager CMDLET generated data set from an Orchestrator Run .NET Script activity onto the Orchestrator data bus.

Last time on as the scripts churn:

As seen before, in order to Run a Configuration Manager PowerShell cmdlet in the Orchestrator Run .NET Script activity, the script must be capsulated in

$VAR = Powershell {

<Script Goes Here>

}

The details of why can be found here.

In the following example I am importing the Configuration Manager PowerShell module, changing to the appropriate PSDrive, and the running the Start-ContentDistribution CMDLET which will distribute content to a Distribution Point. This works great, but as can be seen, I am not attempting to pass any data back onto the Orchestrator data bus.

Click image for a better view:

The issue encountered trying to publish data:

So going with my newly gained wisdom, today I attempted to execute the following script / Run .NET Script activity. This script once again imports the Configuration Manger PowerShell module, changes to the appropriate PSDrive, and then runs the Get-CMDevice cmdlet, placing the results in a variable $isActive. This is all encapsulated in the appropriate code allowing the Configuration Manager script to be run from the Orchestrator activity.

Click image for a better view:

I then have defined Published data that would return the set of data to the Orchestrator data bus.

What I was expecting to see returned was a list of computers (more specifically the active state for a list of computers), however nothing was returned. After some picking around my guess was that the invoked PowerShell 3.0 session does not natively ‘pass’ data back to the calling session which would account for the lack of a returned data set.

And the Fix:

After coming to grips with the fact that I am a mere tourist when it comes to PowerShell development, I turned back to Karl Prosser’s Blog on the various PowerShell issues with the Run. Net Script activity. Sure enough I found what I needed.

Karl Prosser post - Live PowerShell with Karl Prosser

As seen in Karl’s blog, in order to load the returned data set onto the Orchestrator data bus, it must also be ‘passed’ from the invoked 3.0 PowerShell session back into the invoking Run .Net Script 2.0 session. This is quite simple to do. Essentially we will be creating a new object, and the bringing that data back into the calling process, and then targeting it as published data.  

In the below example the custom object is created with the new-object cmd, a property is then declared (isActive) and given a value that is the returned data set of the Get-CMDevice cmd. Once the invoked PowerShell 3.0 session is completed, we can then declare a variable ($Active), and give it a value of the returned object property. This variable can then be specified as returned data and used at any point in our Orchestrator Runbook.

Click image for a better view:

And the Published Data.

Here is the script in text form for copy and paste purposes.

$VAR = Powershell {

import-module ($Env:SMS_ADMIN_UI_PATH.Substring(0,$Env:SMS_ADMIN_UI_PATH.Length-5) + '\ConfigurationManager.psd1')

$PSD = Get-PSDrive -PSProvider CMSite

CD "$($PSD):"

    new-object pscustomobject -property @{

    isActive = Get-CMDevice -Name <computerName> | Select IsActive

    }

}

$Active = $VAR.isActive

Simple Runbook Use / Example:

A very simple example of this process in action could be something like the following. You would like to gather a list of Computers from Active Directory, run the Configuration Manager Get-CMDevice CMDLET for each computer determining if the computer is Active or Inactive, and then finally take some sort of action against those that are inactive (send an email in this case). Mind you this is just a very simple example intended to demonstrated the publishing and re-use of CM PowerShell generated data. There is a TON you could do with CM, PowerShell, and Orchestrator together.

To begin with I've place thee activities in the Runbook, the first being Get Computer from the active directory integration pack, second a Run .NET Script, and third a Send Email activity.

Get Computer is configured to pull back all servers.

The Run .NET Script is basically executing Get-CMDevice - Name <Computer Returned from AD> | Select ClinetActiveStatus. Also included in the PowerShell is all of the necessary additional items discussed in this blog. I am also publishing the contents of the $Active variable.

Click image for a better view:

On the link between the Run .NET Script activity and the Send Email activity is the following logic - Active = @{ClientActiveStatus = 0}. This is the first use of the published data returned from the PowerShell execution. In this case, the Runbook will only progress onto the Send Email activity for any computer that has been detected as being inactive with the Get-CMDevice CMDLET.

Click image for a better view:

And finally, very simple, I am sending an email which includes the computer name for each computer found as inactive.

Conclusion:

Well I think I have it this time, or at least making progress. In this blog posting we have extended on simply running Configuration Manager PowerShell cmdlets from an Orchestrator Run .NET Script activity to also passing data from the Configuration Manager PowerShell script onto the Orchestrator data bus. I've given a very simple example here, but make no mistake there is allot of power and automation to be had with the union of Configuration Manager PowerShell CMDLETS and System Center Orchestrator. Hopefully this post has been helpful in getting you on your way to Orchestrator / Configuration Manager PowerShell automation.

Comments

  • Anonymous
    January 01, 2003
    thanks

  • Anonymous
    January 01, 2003
    Thanks Mitch.. neilp

  • Anonymous
    February 07, 2013
    Awesome follow up to your first blog.

  • Anonymous
    September 23, 2013
    I can't seem to get this working in Orchestrator.  Here is some very basic code I'm using as an example to output to a platform event, but I can't get any data to output.  When I run the below code in PS by itself, it is successful.  When I run it in a Runbook it is also successful just doesn't throw any data to the platform event.  I have published goodlistout and badlistout.  I am using those published variables in my platform event, but no data is thrown.   $PSE = Powershell { $goodlist = "1,2,3,4" $badlist = "a,b,c,d" new-object pscustomobject -property @{goodlistps2 = $goodlist} new-object pscustomobject -property @{badlistps2 = $badlist} } $goodlistout = $PSE.goodlistps2 $badlistout = $PSE.badlistps2

  • Anonymous
    January 31, 2014
    Hey, Neil- I really enjoy your blogs and presentations. This seems helpful, but (as it was written pre-R2) I am not sure it is this simple any longer as having the Runbook Designer and Configuration Manager on the same server causes the CM console to crash. Therefore, I've been attempting to run the CM cmdlets remotely using Orchestrator to remove CM devices. It works when I run the commands manually in a PS session, but does not remove a CM device when run with Orchestrator. The output in the Runbook Tester says the script is successful, but the CM device remains. If you have any suggestions, I'm all ears. My script reads: Powershell { $remotePC = "" $remoteUserName = "" $remotePassword = "*********" $pass = ConvertTo-SecureString $remotePassword -AsPlainText -Force $cred = new-object System.Management.Automation.PSCredential($remoteUserName, $pass) Set-ExecutionPolicy Unrestricted -Force Enter-PSSession -ComputerName $remotePC -Credential $cred import-module "C:Program Files (x86)Microsoft Configuration ManagerAdminConsolebinConfigurationManager.psd1" cd : Remove-CMDevice -DeviceName -Force }