Skip to content

ConfigMgr··2 min read

ConfigMgr Client Update

Sometimes, it's really useful to update your ConfigMgr client using PowerShell. This is a common little script I use in Demo Labs where there might be multiple Configmgr environments, and management points in the same domain.

While client push certainly has it’s place in the world, it assumes a lot of things. Like boundary groups being correctly configured, and a clients ability to know what management point it should talk to.

There are also some awkward security conversation to be had such as, service accounts with local admin on every machine in an environment are typically less than ideal.

Determine a site Code

I currently help support 36 “unique” environments. Nine ConfigMgr Labs, in four domains. Because all of the Configmgr servers are in the same domain, things like AD site assignment aren’t practical or frankly needed. Additionally, it’s takes a second for the client to come to an answer.

I have found it’s way faster to determine the current management point, and use the current management point to direct the install. With a quick CIM (or WMI call) you can determine this.

$ManagementPoint = (Get-CimInstance -ClassName SMS_Authority -Namespace 'root\ccm').CurrentManagementPoint

For the purposes of my lab, the MP is always on the primary site server as result, a little gentle manipulation converts the MP information to a site code name.

$siteCodePath = (Get-CimInstance -ClassName SMS_Authority -Namespace 'root\ccm').Name.Replace(":","_")

Calling for Install

When you use client push, the client has to download the full contents of the CCM installer from the management point. Every time. We can do exactly what it does but as a “pull” instead of a push.

First we check to see if there is a scratch space where we want to copy the client content to, and if not create it. Then we just copy the content from the management point.

if(!(Test-Path -Path C:\Scratch\CurrentClient)){
    Write-Verbose -Message "The Scratch Space DOESNT exist, creating and downloading Client Info"
    New-Item -ItemType Directory -Path C:\Scratch\CurrentClient | Out-Null
    Copy-Item -Path \\$($ManagementPoint)\$($siteCodePath)\Client -Destination C:\Scratch\CurrentClient -Recurse
    Set-Location -Path C:\Scratch\CurrentClient\Client
    Write-Verbose -Message "Now starting the install..."
    .\ccmsetup.exe /source:C:\Scratch\CurrentClient\Client /mp:$($ManagementPoint)
    Write-Verbose -Message "Now opening log directory..."
    explorer.exe C:\Windows\ccmsetup\Logs
}
else{
    Write-Verbose -Verbose "Scratch space existed, cleaning up and re-downloading..."
    Remove-Item -Path C:\Scratch\CurrentClient -Recurse -Force
    New-Item -ItemType Directory -Path C:\Scratch\CurrentClient | Out-Null
    Copy-Item -Path \\$($ManagementPoint)\$($siteCodePath)\Client -Destination C:\Scratch\CurrentClient -Recurse
    Set-Location -Path C:\Scratch\CurrentClient\Client
    Write-Verbose -Message "Now starting the install..."
    .\ccmsetup.exe /source:C:\Scratch\CurrentClient\Client /mp:$($ManagementPoint)
    Write-Verbose -Message "Now opening log directory..."
    explorer.exe C:\Windows\ccmsetup\Logs
}
Note

If you run this interactively on the client, the example here will open the default log directory so you can then watch the install.

Putting it all together

We can put all of the code together as a single function, and run it on the client.

Function Update-CMClient{
    [cmdletbinding()]
    param(
        [Parameter(HelpMessage = "Provide the Management Point, if you don't provide one I'll guess." , Mandatory = $FALSE)]
        [string]$ManagementPoint
    )
    if(!($PSBoundParameters.ContainsKey('ManagementPoint'))){
        $ManagementPoint = (Get-CimInstance -ClassName SMS_Authority -Namespace 'root\ccm').CurrentManagementPoint
    }
    Write-Verbose -Message "Determined the MP is: $($ManagementPoint)"
    $siteCodePath = (Get-CimInstance -ClassName SMS_Authority -Namespace 'root\ccm').Name.Replace(":","_")
    Write-Verbose -Message "Determined the Site Code Info to be: $($siteCodePath)"
    if(!(Test-Path -Path C:\Scratch\CurrentClient)){
        Write-Verbose -Message "The Scratch Space DOESNT exist, creating and downloading Client Info"
        New-Item -ItemType Directory -Path C:\Scratch\CurrentClient | Out-Null
        Copy-Item -Path \\$($ManagementPoint)\$($siteCodePath)\Client -Destination C:\Scratch\CurrentClient -Recurse
        Set-Location -Path C:\Scratch\CurrentClient\Client
        Write-Verbose -Message "Now starting the install..."
        .\ccmsetup.exe /source:C:\Scratch\CurrentClient\Client /mp:$($ManagementPoint)
        Write-Verbose -Message "Now opening log directory..."
        explorer.exe C:\Windows\ccmsetup\Logs
    }
    else{
        Write-Verbose -Verbose "Scratch space existed, cleaning up and re-downloading..."
        Remove-Item -Path C:\Scratch\CurrentClient -Recurse -Force
        New-Item -ItemType Directory -Path C:\Scratch\CurrentClient | Out-Null
        Copy-Item -Path \\$($ManagementPoint)\$($siteCodePath)\Client -Destination C:\Scratch\CurrentClient -Recurse
        Set-Location -Path C:\Scratch\CurrentClient\Client
        Write-Verbose -Message "Now starting the install..."
        .\ccmsetup.exe /source:C:\Scratch\CurrentClient\Client /mp:$($ManagementPoint)
        Write-Verbose -Message "Now opening log directory..."
        explorer.exe C:\Windows\ccmsetup\Logs
    }
}
Update-CMClient -Verbose

Bonus Points

When I use this script, I typically remove the function block, and ship the entire script via invoke-command. This then let’s me kick the update on all of my remote hyper-v clients at once.

Technically, you could use something like run scripts to do this as well if you wanted to.

Warning

This script is intended for use in a small lab environment. I would not suggest downloading the CMClient manually via SMB in a normal standard environment. Instead I would use this as a thought exercise for how to automate things in your lab.

Comments

Comments are GitHub Discussions, loaded on request.