Invoke Run Script via PowerShell and Collect the Result

I'm a big fan of the Run Script feature in ConfigMgr, since it allows me to run a PowerShell script on any ConfigMgr client without having to worry about remote PowerShell being enabled, or having any special permissions on the target machine itself.

Here is an example on how to invoke a run script via PowerShell on a single machine, and collect the result. It is not very pretty, but it works 🙂 For multiple results, like when targeting a collection of devices, you're better off returning the Run Script result as JSON and then read it. But that's for another day.

In this example the Run Script used retrieved the .NET Framework version on the client, and If you have any ideas for improvements, please let me know in the comments below. Also, you can find the "Get .NET Framework Version" Run Script used here: https://github.com/DeploymentResearch/DRFiles/blob/master/Scripts/GetNetFrameworkVersion.ps1

Sample output from the script

The InvokeRunScriptOnDevice.ps1 script

# Run a script on device via Run Script, and collect the result

# Parameters
$ScriptName = "Get .NET Framework Version"
$ComputerName = "CHI-W10PEER-008"
$ProviderMachineName = "cm01.corp.viamonstra.com"
$SiteCode = "PS1"

# Import the ConfigurationManager.psd1 module 
if((Get-Module ConfigurationManager) -eq $null) {
    Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1"
}

# Connect to the site's drive if it is not already present
if((Get-PSDrive -Name $SiteCode -PSProvider CMSite -ErrorAction SilentlyContinue) -eq $null) {
    New-PSDrive -Name $SiteCode -PSProvider CMSite -Root $ProviderMachineName 
}

# Set the current location to be the site code.
Set-Location "$($SiteCode):\" 

# Main code
$ScriptGuid = (Get-CMScript -ScriptName $ScriptName -Fast).ScriptGuid
If (!($ScriptGuid)){
    Write-Warning "Could not find a Run Script named $ScriptName, aborting..."
    Break
}

$CMDevice = Get-CMDevice -Name $ComputerName
$OperationID = (Invoke-CMScript -ScriptGuid $ScriptGuid -Device $CMDevice -PassThru).OperationID

# Get script output, wait a maximum of five minuters
$NumberOfLoops = 30
$LoopInterval = 10 #Seconds
$i = 1
[System.Collections.ArrayList]$VMList = @()
do {

    $Operation = Get-CimInstance -Namespace root\SMS\Site_$SiteCode -ClassName SMS_ScriptsExecutionStatus -Filter "ClientOperationID = '$OperationID'" 
    If ($Operation){
        # Got the status, time to exit loop
        Break
    }
    
    Start-Sleep -Seconds $LoopInterval
    $i++
}
while ($i -le $NumberOfLoops)

# Script output
$Operation.ScriptOutput
About the author

Johan Arwidmark

5 1 vote
Article Rating
Subscribe
Notify of
guest
2 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
Sabry
Sabry
12 days ago

Thanks Johan for the post.

While getting operation status I am getting error:
$Operation = Get-CimInstance -Namespace root\SMS\Site_$SiteCode -ClassName SMS_ScriptsExecutionStatus -Filter "ClientOperationID = '$OperationID'" 

Error:
Get-CimInstance : Invalid namespace 

$Sitecode is correct because it works fine at below step.
# Connect to the site's drive if it is not already present
if((Get-PSDrive -Name $SiteCode -PSProvider CMSite -ErrorAction SilentlyContinue) -eq $null) {
  New-PSDrive -Name $SiteCode -PSProvider CMSite -Root $ProviderMachineName 
}


>