Archive for April, 2010|Monthly archive page
Using PowerShell to Manipulate Clients En-masse
Working with Configuration Manager, I am constantly reminding customers that Configuration Manager is a patient man’s tool. Oftentimes there’s no point in trying to speed the application along, there’s latency built into some of the processes occurring under the Configuration Manager hood and there’s generally not a great deal of point in interfering…
That said, I do like SCCM Client Center from Roger Zander. I personally preferred the look and feel of the old SMS Client Center over the new version, but nonetheless, you can get some great results with the new one.
Anyhow, I digress. As I’ve been mucking about fixing hundreds and hundreds of duplicate GUIDs, I’ve also been monkeying around with PowerShell manipulating clients. I am aware of a number of console extensions that enable you to do this kind of thing to whole collections, but, I’m a command-line guy and I am generally working on customer’s infrastructures so don’t want to be cluttering up the console. Further to this, I now frequently use a sequenced version of the Configuration Manager console which makes adding in extensions a little more complex.
As you’re probably aware, PowerShell makes WMI handling nice and easy. I’m a fan of WMIC (WMIC COMPUTERSYSTEM GET MODEL is my 3rd favourite command line trick) but it isn’t remotable, and won’t run through PSExec
I specifically wanted a few hundred machines to give me a DDR this morning, I was in that kind of mood, so to PowerShell.
Powershell WMI
First thing to do is to create yourself a function. Open the PS console:
Function GenerateDDR
{
$SMSCli = [wmiclass] \\$strComputer\root\ccm:sms_client
$SMSCli.TriggerSchedule("{00000000-0000-0000-0000-000000000003}")
}
You’ll need to press return a couple of times after the last line. Now we can execute:
GenerateDDR MYCOMPUTERNAME
Brilliant. There are a few different trigger actions:
Trigger Actions
Hardware Inventory {00000000-0000-0000-0000-000000000001}
Software Inventory {00000000-0000-0000-0000-000000000002}
Discovery Data Record {00000000-0000-0000-0000-000000000003}
Machine Policy Retrieval & Evaluation {00000000-0000-0000-0000-000000000021}
File Collection {00000000-0000-0000-0000-000000000010}
SW Metering Usage Report {00000000-0000-0000-0000-000000000022}
Windows Installer Source List {00000000-0000-0000-0000-000000000032}
Software Updates Scan {00000000-0000-0000-0000-000000000113}
Software Updates Store {00000000-0000-0000-0000-000000000114}
Software Updates Deployment {00000000-0000-0000-0000-000000000108}
There are also a bunch of other client methods:
EvaluateMachinePolicy, GetAssignedSite, PDPMaintenanceTask, RepairClient, RequestMachinePolicy, ResetGlobalLoggingConfiguration, SetAssignedSite, SetClientProvisioningMode and SetGlobalLoggingConfiguration.
So obviously the above function could be modified easily to a GenerateHW, GenerateSW etc. function just by modifying the last two or three digits of the Trigger type.
Now, using the fantastic file handling available in PS we can remotely run this against loads of machines (as long as they’re powered up and accessible…)
To do this we use the magic FOREACH command:
foreach ($StrComputer in Get-Content D:\ClientFix\test.csv) {GenerateDDR $StrComputer}
The output of this (assuming the machines are powered up) is:
For me, this is a great way of performing bulk live client manipulation. PowerShell is a superb utility, but unless I use it frequently I find I quickly forget the syntax of the commands and have to start from scratch every time. This year I’ve promised myself I’m going to migrate from black screen to blue, time to move on from CMD.EXE.
I had a good bit of help with this work from Greg Ramsey and Don Jones.
Repairing Duplicate GUID issues
On site with a customer who currently have SMS 2003. We’re replacing SMS with ConfigMgr of course, so we deploy the ConfigMgr client with SMS feeding it a parameter for SMS_SLP=NEWSERVER which forces the clients to switch to our new infrastrutcure. So far so good.
Around 50% of the clients show up pretty much immediately, but around 1500 are missing. It eventually turns out that this is because these 1500 machines all had the SMS client duplicated on them in a Ghost image, and now we’ve maintained that ID through the ConfigMgr upgrade.
A bit of a nightmare.
In the past under SMS we would have just deleted the SMSCFG.INI from the Windows folder and restarted the SMS Agent Host service which would have regenerated the GUID, these days the ConfigMgr client certificates don’t much like this, so we have to be a little bit smarter about it. We have our own client installation wrapper, SMSSamurai which we use for the client deployment in the first instance. In a scenario where we know there is going to be difficulty with duplicate GUIDs, we have this wrapper generate a new GUID at install time, but in this instance the duplication was not anticipated.
The main problem now is that the machines need to be powered on to be repaired, so it’s a long slow process. I’ve messed around with trying to script this in Powershell, but there’s no WMI provider for regenerating the GUID, so I’ve fallen back on trusty old Tranguid.exe from the SMS 2003 resource kit and PSexec from Sysinternals.
I’ve created a batch file:
REM Cleaining Up Duplicate GUIDS
REM Firstly we kill off the SMS Agent Host (CCMEXEC) service on the remote machine
TASKKILL /S %1 /IM CCMEXEC.EXE
REM Next we generate a new GUID for the machine
PSEXEC \\%1 -c Tranguid.exe /R
REM Now we start the SMS Agent Service back up
SC \\%1 START CCMEXEC
I save this as DeDupe.bat , then executing dedupe.bat brokenclientmachinename will fix the duplicate GUID.
You can check the fix on the client by checking the ClientIDManagerstartup.log:
The batch file above restarts the SMS Agent Host service once the GUID has been renewed. This will result, a couple of minutes later, in a new heartbeat discovery (DDR) being generated. If you are feeling particularly impatient you can kick off a DDR as soon as the batch file completes.
The final piece of the jigsaw is to run the batch file against all clients. To do this we create a “Non Clients” collection (where Client=NULL)
select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,
SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where SMS_R_System.Client is null
Now use View- Export list to dump this collection to a NonClients.CSV file.
Finally, logged on as a user with admin rights on all PCs run the following:
for /f “skip=1 delims=,” %L in (NonClients.csv) do Dedupe.bat %L
It is possible to wrap this command in a ping task to check that the machine is powered on before attempting the remote commands which will speed the process up considerably.
Onsite here I’m finding that this is repairing around 200 clients per hour. That’s a little slow, so adding a ping test can improve things a bit.
for /f “skip=1 delims=,” %L in (NonClients.csv) do ping –n 1 %L && Dedupe.bat %L
The double & in this command line allows CMD.exe to process the Dedupe.bat file to execute if the ping command produces an errorcode of 0, which it does if the machine responds.
Leave a Comment