Orchestrator, PowerShell, and Configuration Manager are powerful tools, but I often see them used independently, or perhaps two-at-a-time.
Want to launch a PowerShell session from the Configuration Manager Console and run a script? Want to create an Orchestrator runbook that uses the Configuration Manager Orchestrator Integration Packs (OIP) to make some changes? That is fairly common practice, but let’s say we want to run those same actions from our Orchestrator server, perhaps on a scheduled basis or off of some other trigger (hello, Service Manager). We don’t want to have a PowerShell-version and a OIP-version of the same logic, so how do we reuse what we already have? This blog post will explore running PowerShell-based runbooks remotely against your Configuration Manager server.
Permissions
First things first, we need to make sure the account we use throughout this setup is the same service account, and an account that has at least “Read Only Analyst” permissions in the Configuration Manager environment we are working in. This can be done in the Configuration Manager Console in the Administration -> Security -> Administrative Users section.
Additionally, the account we are using must have read-permissions to the files/modules in the Configuration Manager installation directory. More specifically, within the \AdminConsole\bin folder. If this folder cannot be accessed from a remote server, remote commands will not function.
Interacting with Configuration Manager Locally via PowerShell
After permissions are set, we need to confirm we can run PowerShell commands locally from the Configuration Manager virtual machine. In the Configuration Manager Console, click the arrow in the top-left hand corner, and then “Connect via Windows PowerShell ISE,” as shown below:
The PowerShell ISE will launch, with the following code present in the script pane (comments omitted, and lab environment pictured—your environment will differ slightly):
Import-Module ‘C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1’
Set-Location ‘NJV:’
If you change nothing and hit run, you will notice that the PowerShell command line will show your site code (my lab pictured):
We are now able to run Configuration Manager PowerShell cmdlets. For example, Get-CMDeviceCollection would return a list of collections. Verify that a read-only Configuration Manager cmdlet returns results.
Next, we should make the above two lines of code a bit more generic so the code is more portable. For example, you might have changed the install path for Configuration Manager, or might be using a different drive, site, etc. Here is a more generic/portable version:
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):”
Breaking down the above code, line 1 is importing the module, but is grabbing the file path via environment variables that would work with installations that do not use the default drive or path. Line 2 is getting the virtual drive for your Configuration Manager environment, which allows us to run commands against a particular site. Lastly, line 3 is just changing to the drive.
Configuring Remote Permissions
Now that we know Configuration Manager PowerShell is working locally, we will work towards being able to run these same commands from a different virtual machine, the Orchestrator server. The code from the previous section works great on the Configuration Manager server itself, but running that locally on a non-Configuration Manager server would not do the trick. We need to instead run that command within a PowerShell Session (PSSession). PowerShell Sessions are a manner of running commands/scripts on a remote server, without giving full Remote Desktop (RDP) or administrative privileges to the user running those commands. In fact, these PSSessions can be configured so granularly as to only allow specific commands in specific sessions by specific users. We will only scratch the surface here, but it is absolutely worth exploring further later.
Before we can use a PSSession, we must give some level of permissions to the account that will be remoting. We can do this with the following command:
64-bit installation:
Set-PSSessionConfiguration -Name Microsoft.PowerShell -ShowSecurityDescriptorUI
Or
32-bit installation:
Set-PSSessionConfiguration -Name Microsoft.PowerShell32 -ShowSecurityDescriptorUI
Additionally, for the -Name parameter, you could specify a custom PSSession instead, just make sure it is using the appropriate x86 or x64 architecture.
The following confirmation dialog will appear. Select “Yes”:
Add the account you want to use to run commands remotely. In this case, it is the Orchestrator service account (my lab account pictured):
Next, hit OK, and you will be prompted to restart the WinRM service. Select “Yes”:
Remoting to Configuration Manager from Orchestrator Server
Now that we have setup our permissions, verified the Configuration Manager server can run the PowerShell cmdlets we need, and setup our PSSession, we have arrived at the good part! To open a remote session to the Configuration Manager server, we will first create a new PSSession. That looks like the following (lab environment shown):
$Session = New-PSSession -ComputerName CM01 -ConfigurationName Microsoft.PowerShell
Note, that if you are using the 32-bit session, you must change the Configuration Name. Additionally, “CM01” should change to the name of your Configuration Manager server.
Now that our session is created, we can use it within the Invoke-Command cmdlet. Let’s verify we can talk to the Configuration Manager server with a simple script block that does nothing.
$ReturnData = Invoke-Command -Session $Session -ScriptBlock {
# Specific code goes here
Exit-PSSession
}
Remove-PSSession -Session $Session
Here, we are calling the code within the curly brackets, and we are running it within the PSSession on our remote Configuration Manager server. We are paying special attention to exiting the session when we are done, and removing the session when it is no longer needed. Otherwise, there is a limit to how many sessions can be open at once.
The last step is to load our Configuration Manager cmdlets, change to the PS drive, and verify we can talk to Configuration Manager (remotely this time!). To do so, we take the code from our previous section and incorporate it into the script block we just created. The final code would look as follows:
$Session = New-PSSession -ComputerName CM01 -ConfigurationName Microsoft.PowerShell
$ReturnData = Invoke-Command -session $Session -ScriptBlock {
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):”
# Get a single collection to validate connectivity
Get-CMDeviceCollection | select -first 1
Exit-PSSession
}
$ReturnData
Remove-PSSession -Session $Session
Note in the above code, we are also making the “Get-CMDeviceCollection” call and retrieving the first collection from our list of all collections. That data is being returned by the script block and stored in the “ReturnData” variable. We then output the variable.
Orchestrator Time
If we can retrieve any amount Configuration Manager data using the above code block, then we know we are talking to Configuration Manager via PowerShell on a remote machine. The next steps would be to utilize this plumbing code within an Orchestrator runbook that actually does something. Using a “Run .Net Activity” configured to use PowerShell would do the trick, ideally calling a script on the server or a file share (much easier to manage). For example:
We will not go into more detail with the runbook part here, as there are many examples out there. That being said, the script we created here could just as easily be used in other automation tools that utilize PowerShell—even Windows Task Scheduler. Orchestrator does give us some nice additional functionality possibilities, such as variable usage, or integration with Service Manager. For example, this runbook could be used as a Runbook Activity as part of the activity chain in a Service Request to install some software via Configuration Manager.
When using PowerShell heavily in Orchestrator, it is important to note that Orchestrator can only run version 2 of PowerShell natively. Luckily, there is a registry change you can make to allow Orchestrator to run the latest installed version. If you missed that blog post, check it out here: https://cireson.com/blog/hitting-limits-and-breaking-through-making-orchestrator-work-for-you/
Final Thoughts
So why integrate these tools in this way? It might be more complicated to set-up, but it is hard to argue against the benefits:
- Portability to future automation tools. You won’t be using Orchestrator forever.
- Flexibility in the logic. Orchestrator or any drag-and-drop automation tool will limit what you can ultimately accomplish.
- Reuse the same ad-hoc administrative scripts in an automated way. Stop redoing work!
- Consistency. Not all software has direct Orchestrator integration, but most can be integrated via PowerShell.
B-b-but I don’t know any PowerShell, I’m not a “coder,” and I want to keep using drag-and-drop or GUI-based tools! That’s perfectly fine, and I use them too: there is a tool for every job and it’s never an “all-or-nothing” approach. You don’t need to be a “coder” to start using PowerShell; PowerShell is designed to be used by folks of many backgrounds– coders, scripters, and GUI-users alike. Just try something simple to get started… your first script doesn’t have to be a masterpiece.
Ultimately, PowerShell isn’t going away: even basic usage will help you and your organization. Happy scripting!