There are a lot of ways to install the SCCM client: automatic client push, push via the console, GPOs and many more. I will be sharing here a simple PowerShell script meant to be run interactively. The script will install the SCCM client using a batch file stored on a file share accessible to all machines.
PSExec is part of Microsoft Windows Sysinternals PsTools and can be obtained here. For those who are not familiar with it, it is a powerful tool used to remotely execute commands on remote machines. It should be placed in an Execution subfolder compared to where the PowerShell script is placed, otherwise, modify the code to point to where PSExec is actually located.
The full script is below. Many lines have comments in them to make the script easy to read. I will further explain some code as well. Watch out for the & sign being converted to & by WordPress:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
Do { $ListOrManual = Read-Host "Would you like to run the script using an input list or manual entry? (L)ist/(M)anual" if ($ListOrManual -eq 'L') #If user chooses to use an input list { $TestList = Test-Path .\Machines.txt #Tests if the input list is present if ($TestList) { $Date = Get-Date -Format yyyy.MM.dd-HH.mm.ss #Formats the date at script runtime to rename and move pre-existing files in order to avoid deleting potentially needed lists from previous runs Rename-Item -Path .\Output\Success.txt -NewName Success-$Date.txt -ErrorAction SilentlyContinue Rename-Item -Path .\Output\Failure.txt -NewName Failure-$Date.txt -ErrorAction SilentlyContinue Move-Item .\Output\*.txt .\Output\Archive $PSExec = ".\Execution\PSExec.exe" $ComputersList = Get-Content .\Machines.txt #Parse the input list and populate it in ComputersList $ComputersCount = $ComputersList.Count Write-Host "You are attempting to install the CM 2012 client on " -NoNewLine; Write-Host "$ComputersCount devices." -ForegroundColor Yellow $Confirm = Read-Host "Are you sure you want to proceed? Y/N" #Confirmation required to proceed if ($Confirm -eq 'Y') { $FailureCount = 0 $SuccessCount = 0 foreach ($Computer in $ComputersList) #Loop for each item in the input list { Write-Host "Running CM installation on $Computer" Remove-Item "\\$Computer\Admin$\System32\Tasks\Microsoft\Microsoft\Configuration Manager\Configuration Manager Client Retry Task" -ErrorAction SilentlyContinue #Removes the CM 2012 Client Retry Task that may be present due to a bug in CM2012 R2 Pre-SP1 &$PSExec -s \\$Computer cmd /c \\$ServerHostingClientFiles\CMClient_Install\Inst_CM.cmd 2>$Var | Out-Null #PSExec will target the current machine in the list and run the CM manual client install script in SYSTEM context, PSExec output redirected to lala land if ($LastExitCode -Eq 0) { $Computer | Out-File -Encoding ascii -Append .\Output\Success.txt #PSExec succeeded in copying the files and launching setup on the target machine Write-Host "CM installation " -NoNewLine; Write-Host "was successfully launched" -ForegroundColor Green -NoNewLine; Write-Host " on $Computer" Write-Host "--------------------------------------------------" $SuccessCount++ } else { $Computer | Out-File -Encoding ascii -Append .\Output\Failure.txt #PSExec failed in copying the files and launching setup on the target machine Write-Host "CM installation " -NoNewLine; Write-Host "could not be launched" -ForegroundColor Red -NoNewLine; Write-Host " on $Computer" Write-Host "--------------------------------------------------" $FailureCount++ } } Write-Host "Finished executing on " -NoNewLine; Write-Host "$ComputersCount devices:" -ForegroundColor Yellow -NoNewLine; Write-Host " $SuccessCount installation(s) succeeded, " -ForegroundColor Green -NoNewLine; Write-Host "$FailureCount installation(s) failed." -ForegroundColor Red Pause } else { Write-Host "CM2012 client installation aborted by user!" Pause } } else { Write-Host "The Machines.txt list is missing. Make sure the file exists and is populated." #If Machines.txt list is missing, inform the user running the script accordingly Pause } } if ($ListOrManual -eq 'M') #If user chooses to use manual target entry { $Target = Read-Host "Please input target machine name" #Takes from the user the target device to deploy to $PSExec = ".\Execution\PSExec.exe" Remove-Item "\\$Target\Admin$\System32\Tasks\Microsoft\Microsoft\Configuration Manager\Configuration Manager Client Retry Task" -ErrorAction SilentlyContinue #Removes the CM 2012 Client Retry Task that may be present due to a bug in CM2012 R2 Pre-SP1 &$PSExec -s \\$Target cmd /c \\$ServerHostingClientFiles\CMClient_Install\Inst_CM.cmd 2>$Var | Out-Null #PSExec will target the current machine in the list and run the CM manual client install script in SYSTEM context, PSExec output redirected to lala land if ($LastExitCode -Eq 0) { Write-Host "CM installation " -NoNewLine; Write-Host "was successfully launched" -ForegroundColor Green -NoNewLine; Write-Host " on $Target" Write-Host "--------------------------------------------------" } else { Write-Host "CM installation " -NoNewLine; Write-Host "could not be launched" -ForegroundColor Red -NoNewLine; Write-Host " on $Target" Write-Host "--------------------------------------------------" } Pause } if ($ListOrManual -ne "L" -and $ListOrManual -ne "M") #If user made a wrong selection { Write-Host "Incorrect selection made. Please input either 'L' to use a list or 'M' for manual entry ..." } $Retry = Read-Host "Would you like to run the script again? Y/N" #Rerun script if desired } While ($Retry -eq 'Y') Write-Host "Have a good day!" Pause |
The script first asks the user(s) running it if they would like to use a list of machines as input or specify a single manual entry to install the SCCM client on.
If the user chooses to use a list input, the script checks for the presence of a file named Machines.txt that should be located in the same folder as the PowerShell script. The script then renames output log files from previous runs to avoid overwriting them, retrieves all the machine names from the Machines.txt file and asks the user for confirmation before proceeding since the number of machines could be large.
If the user confirms, the script will perform two actions. The first is to attempt to remove a scheduled task which is present due to a bug in SCCM 2012 R2 for versions prior to SP1.
1 |
Remove-Item "\\$Computer\Admin$\System32\Tasks\Microsoft\Microsoft\Configuration Manager\Configuration Manager Client Retry Task" -ErrorAction SilentlyContinue |
The scheduled task is named Configuration Manager Client Retry Task and the bug probably exists due to an oversight that places this scheduled task in the scheduled tasks folder Microsoft\Microsoft\Configuration Manager instead of Microsoft\Configuration Manager where all the other SCCM client related tasks are.
Microsoft confirmed that this behavior has been fixed in SCCM 2012 R2 SP1. Unfortunately, they also confirmed that no hotfix exists for pre-SP1 version, you either have to fix it manually as the script does, or upgrade to SP1 to squash the bug. As Windows 10 becomes more relevant, you would want to upgrade to SP1 (and CU2) soon in all cases.
In the next step, the PowerShell script uses PSExec to remotely execute the batch file responsible for installing the SCCM client. The batch file consists of ccmsetup.exe with any additional parameters that are needed in your environment. We used the batch file as well to copy all the client setup content locally before launching ccmsetup in our environment. The script will monitor the return from PSExec to determine if the setup was successfully launched on the target machine.
1 |
if ($LastExitCode -Eq 0) |
If the exit code was ‘0’, PSExec remote execution was successful, if not, it failed in launching the SCCM client setup. The script will track the number of successes and failures and will report at the end of the execution the total numbers.
Manual entry is similar in behavior, it will ask the user to input a machine’s name and will proceed to perform the same two actions and monitor PSExec remote execution attempt. In the end, the user running the script is asked if they would like to run the script again or exit the session.
As you can see, the script is simple in nature and there is a lot of room for improvements if desired. For example, parallel execution can be implemented to speed up the process of installing numerous SCCM clients or log files for SCCM client setup can be monitored. Feel free to improve the script as you wish.