Tuesday, April 28, 2009

WSUS: Clients overwriting each other


I discovered an interesting issue recently where a number of machines that were clones of each other were using the same IDs to report to WSUS and were therefore constantly overwriting each other in the WSUS database.

A quick run of this script against the machines was able to force a change of those IDs and set a registry entry flag so that if the script were run again (such as from a computer startup GPO), it wouldn't reset the IDs again.


Set oShell = CreateObject("WScript.Shell")

sRegKey = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate"

' suppress error in case values does not exist
On Error Resume Next

' check for marker

sIDDeleted = oShell.RegRead( sRegKey & "\IDDeleted")

' to be sure values is only deleted once, test on marker
If sIDDeleted <> "yes" Then
' delete values
oShell.RegDelete sRegKey & "\AccountDomainSid"
oShell.RegDelete sRegKey & "\PingID"
oShell.RegDelete sRegKey & "\SusClientId"

' Stop and start the Automatic updates service
oShell.Run "%SystemRoot%\system32\net.exe stop wuauserv", 0, True
oShell.Run "%SystemRoot%\system32\net.exe start wuauserv", 0, True

' Run wuauclt.exe with resetauthorizations
Cmd = "%SystemRoot%\system32\wuauclt.exe /resetauthorization /detectnow"
oShell.Run sCmd, 0, True

' create marker
oShell.RegWrite sRegKey & "\IDDeleted", "yes"
End If


We actually chose to run the script on the target machines using SCHTASKS.EXE from the Support Tools. I created a text file containing the names of all of the target machines and simply ran this script:

@echo off
FOR /F %%i IN (WSUS_Fix_Targs.txt) DO (
schtasks /create /tn "%%i_WSUS_SID_Fix" /tr "wscript.exe \\server\share\WSUS_Fix.vbs" /sc once /st 15:00 /ru domain\adminuser /rp userpassword /z /s %%i
)

Monday, April 20, 2009

SCCM: selecting objects not in a collection


Although SCCM provides a way of restricting a result set to a collection, it doesn't provide a way of excluding another collection from your collection.

It's not that hard, if you get the Collection ID of the collection that you want to exclude, which you'll find in the properties of your collection and use WQL to rule out the membership of that collection.

select sms_r_system.resourceid, sms_r_system.name
from sms_r_system
where resourceid not in
(
select sms_r_system.resourceid
from sms_cm_res_coll_[ID], sms_r_system
where sms_r_system.resourceid = sms_cm_res_coll_[ID].resourceid
)


You can also chain them together. So, for example, to execute a query for a collection that you want to patch and automatically reboot the machines, but you want to exclude your 2 collections for manual patching and suppressed reboots and for reporting purposes you want to exclude the machines that don't have a client:

select sms_r_system.resourceid, sms_r_system.name
from sms_r_system
where resourceid not in
(
select sms_r_system.resourceid
from sms_cm_res_coll_sms00001, sms_r_system
where sms_r_system.resourceid = sms_cm_res_coll_sms00001.resourceid
)
and resourceid not in
(
select sms_r_system.resourceid
from sms_cm_res_coll_sms00002, sms_r_system
where sms_r_system.resourceid = sms_cm_res_coll_sms00002.resourceid
)
and resourceid not in
(
select sms_r_system.resourceid
from sms_cm_res_coll_sms00003, sms_r_system
where sms_r_system.resourceid = sms_cm_res_coll_sms00003.resourceid
)


Cheers,
Sean


PS: If anyone can tell me how I can place a comment in WQL code, I'd love to know!


PPS: It looks like the SQL convention of using /* comment */ works as I found it in some of the inbuilt reports. I could have sworn I'd tried this and it didn't work, but maybe I had them the wrong way around. /* embarrassed grin */