I worked on this this morning. Basically, there were about a hundred PC's here that weren't recieving updates for the antivirus application due to a flaw in the way updates are roled out and the way Windows handles errors or problems.
Ordinarily, if a script wasn't used, these steps would have to be carried out manually That would take days! After this script was written it took just under an hour to update all one hundred or so PC's.
In case it's ever useful to anyone else, I've posted it here. It's nice to have the freedom to write code in work! It's a nice medium for me.
I'll have to blog more often. I've not really taken much time to do it lately.
The script will log each part and if a computer isn't connected to the network at the time it will log that no connection could be made and move onto the next one in the Excel spreadsheet.
Here are the rough steps that the script performs in edition to the logging and logic.
1. Stop the Automatic Updates Service2. Delete the %WINDIR%\softwaredistribution folder3. Delete the HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate keys and subkeys.4. Start the Automatic updates Service5. Send a wuauclt.exe /resetauthorization /detectnow command to sysem bEnableLogging = TruebIncludeDateStamp = TruebPrependDateStampInLogFileName = FalsesLogFileLocation = "relative"sLogFileName = "errors.txt"sOverWriteORAppend = "append"vLogMaximumLines = 0vLogMaximumSize = 0 Sub LogToFile(Message) If bEnableLogging = False Then Exit Sub Const ForReading = 1Const ForWriting = 2Const ForAppending = 8 Set oLogFSO = CreateObject("Scripting.FileSystemObject") If sLogFileLocation = "relative" ThenSet oLogShell = CreateObject("Wscript.Shell")sLogFileLocation = oLogShell.CurrentDirectory & "\"Set oLogShell = NothingEnd If If bPrependDateStampInLogFileName ThensNow = Replace(Replace(Now(),"/","-"),":",".")sLogFileName = sNow & " - " & sLogFileNamebPrependDateStampInLogFileName = FalseEnd If sLogFile = sLogFileLocation & sLogFileName If sOverWriteORAppend = "overwrite" ThenSet oLogFile = oLogFSO.OpenTextFile(sLogFile, ForWriting, True)sOverWriteORAppend = "append"ElseSet oLogFile = oLogFSO.OpenTextFile(sLogFile, ForAppending, True)End If If bIncludeDateStamp ThenMessage = Now & " " & MessageEnd If oLogFile.WriteLine(Message)oLogFile.Close If vLogMaximumLines > 0 ThenSet oReadLogFile = oLogFSO.OpenTextFile(sLogFile, ForReading, True)sFileContents = oReadLogFile.ReadAllaFileContents = Split(sFileContents, vbCRLF)If Ubound(aFileContents) > vLogMaximumLines ThensFileContents = Replace(sFileContents, aFileContents(0) & _vbCRLF, "", 1, Len(aFileContents(0) & vbCRLF))Set oLogFile = oLogFSO.OpenTextFile(sLogFile, ForWriting, True)oLogFile.Write(sFileContents)oLogFile.CloseEnd IfoReadLogFile.CloseEnd If If vLogMaximumSize > 0 ThenSet oReadLogFile = oLogFSO.OpenTextFile(sLogFile, ForReading, True)sFileContents = oReadLogFile.ReadAlloReadLogFile.ClosesFileContents = RightB(sFileContents, (vLogMaximumSize*2))Set oLogFile = oLogFSO.OpenTextFile(sLogFile, ForWriting, True)oLogFile.Write(sFileContents)oLogFIle.CloseEnd If oLogFSO = NullEnd Sub function Ping(byval strName)dim objFSO, objShell, objTempFile, objTSdim sCommand, sReadLinedim bReturn set objShell = WScript.CreateObject("Wscript.Shell")set objFSO = CreateObject("Scripting.FileSystemObject") 'Set default return valuebReturn = false 'Create command line to ping and save results to a temp filesCommand = "cmd /c ping.exe -n 3 -w 1000 " & strName & " > temp.txt" 'Execute the commandobjShell.run sCommand, 0, true 'Get the temp fileset objTempFile = objFSO.GetFile("temp.txt")set objTS = objTempFile.OpenAsTextStream(1) 'Loop through the temp file to see if "reply from" is found,'if it is then the ping was successfuldo while objTs.AtEndOfStream <> truesReadLine = objTs.ReadLineif instr(lcase(sReadLine), "reply from") > 0 thenbReturn = trueexit doend ifloop 'Close temp file and release objectsobjTS.closeobjTempFile.deleteset objTS = nothingset objTempFile = nothingset objShell = nothingset objFSO = nothing 'Return valuePing = bReturnend function '---------------- Input Computer Name --------------------- On Error Resume NextDim strComputerDim intLoopCount, dir, objExcel, objWorkbookSet objExcel = CreateObject("Excel.Application") 'Gets the directory where our script is running fromdir = CreateObject("Scripting.FileSystemObject").GetParentFolderName(Wscript.ScriptFullName) 'Open our EXCEL fileSet objWorkbook = objExcel.Workbooks.Open(dir & "\Computers-Report.xls") intLoopCount = 1 'Do Until objExcel.Cells(intLoopCount,1).Value = ""Do While Not IsEmpty(objExcel.Cells(loopCount, 1).Value) strComputer = objExcel.Cells(intLoopCount,1).Value StrComputer=UCase(StrComputer) 'ping the StrComputer to see if it is accessiblebPingtest = ping(StrComputer) If bPingtest = FALSE ThenLogToFile "" & strComputer & "Is not accessible. Ping failed."Loop end IF'''----------------Stop Automatic Updates Service--------------------'''On Error Resume Next' NB strService is case sensitive.strService = " 'wuauserv' "Set objWMIService = GetObject("winmgmts:" _& "{impersonationLevel=impersonate}!\\" _& strComputer & "\root\cimv2")Set colListOfServices = objWMIService.ExecQuery _("Select * from Win32_Service Where Name ="_& strService & " ")For Each objService in colListOfServicesobjService.StopService()Next LogToFile "" & strComputer & "Automatic update service has been stopped."''''----------------Stop BITS Service--------------------'''On Error Resume Next' NB strService is case sensitive.strService = " 'BITS' "Set objWMIService = GetObject("winmgmts:" _& "{impersonationLevel=impersonate}!\\" _& strComputer & "\root\cimv2")Set colListOfServices = objWMIService.ExecQuery _("Select * from Win32_Service Where Name ="_& strService & " ")For Each objService in colListOfServicesobjService.StopService()Next LogToFile "" & strComputer & "Background Intelligent Transfer Service has been stopped"'WScript.Echo "Background Intelligent Transfer Service has been stopped" ''''----------------- Delete Folder and Reg Keys -------------------------------- strExe = "cmd.exe /C rmdir %WINDIR%\SoftwareDistribution /S /Q && cmd.exe /C REG DELETE HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate /f" ' Connect to WMI'set objWMIService = getobject("winmgmts://"_& strComputer & "/root/cimv2") ' Obtain the Win32_Process class of object. Set objProcess = objWMIService.Get("Win32_Process")Set objProgram = objProcess.Methods_( _"Create").InParameters.SpawnInstance_objProgram.CommandLine = strExe 'Execute the program now at the command line. Set strShell = objWMIService.ExecMethod( _"Win32_Process", "Create", objProgram)LogToFile "" & strComputer & "The software Distribution Folder and WindowsUpdate regsitry keys have been deleted."'WScript.Echo "The software Distribution Folder and WindowsUpdate regsitry keys have been deleted." '------------------ Start Automatic Update Service -------------'''On Error Resume Next' NB strService is case sensitive.strService = " 'wuauserv' "Set objWMIService = GetObject("winmgmts:" _& "{impersonationLevel=impersonate}!\\" _& strComputer & "\root\cimv2")Set colListOfServices = objWMIService.ExecQuery _("Select * from Win32_Service Where Name ="_& strService & " ")For Each objService in colListOfServicesobjService.StartService()Next LogToFile "Windows Updates Service has been Started on " & strcomputer 'WScript.Echo "Windows Updates Service has been Started on " & strcomputer '''------------------ Start BITS Service -------------'''On Error Resume Next' NB strService is case sensitive.strService = " 'BITS' "Set objWMIService = GetObject("winmgmts:" _& "{impersonationLevel=impersonate}!\\" _& strComputer & "\root\cimv2")Set colListOfServices = objWMIService.ExecQuery _("Select * from Win32_Service Where Name ="_& strService & " ")For Each objService in colListOfServicesobjService.StartService()Next LogToFile "Background Intelligent Transfer Service has been Started on " & strcomputer 'WScript.Echo "Background Intelligent Transfer Service has been Started on " & strcomputer ''-------------- Force Checking to WSUS server by issueing a wuauclt.exe /resetauthorization /detectnow ------------ strExe = "cmd.exe /C wuauclt.exe /resetauthorization /detectnow" ' Connect to WMI'set objWMIService = getobject("winmgmts://"_& strComputer & "/root/cimv2") ' Obtain the Win32_Process class of object. Set objProcess = objWMIService.Get("Win32_Process")Set objProgram = objProcess.Methods_( _"Create").InParameters.SpawnInstance_objProgram.CommandLine = strExe 'Execute the program now at the command line. Set strShell = objWMIService.ExecMethod( _"Win32_Process", "Create", objProgram)LogToFile "" & strComputer & "Force checkin has been sent. Process Complete."'WScript.Echo "Force checkin has been sent. Process Complete." intLoopCount = intLoopCount + 1 LoopLogToFile "*********************************************************"objExcel.Workbooks.CloseobjExcel.quitobjExcel = EmptyobjWorkbook = Empty
1. Stop the Automatic Updates Service2. Delete the %WINDIR%\softwaredistribution folder3. Delete the HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate keys and subkeys.4. Start the Automatic updates Service5. Send a wuauclt.exe /resetauthorization /detectnow command to sysem
bEnableLogging = TruebIncludeDateStamp = TruebPrependDateStampInLogFileName = FalsesLogFileLocation = "relative"sLogFileName = "errors.txt"sOverWriteORAppend = "append"vLogMaximumLines = 0vLogMaximumSize = 0
Sub LogToFile(Message)
If bEnableLogging = False Then Exit Sub
Const ForReading = 1Const ForWriting = 2Const ForAppending = 8
Set oLogFSO = CreateObject("Scripting.FileSystemObject")
If sLogFileLocation = "relative" ThenSet oLogShell = CreateObject("Wscript.Shell")sLogFileLocation = oLogShell.CurrentDirectory & "\"Set oLogShell = NothingEnd If
If bPrependDateStampInLogFileName ThensNow = Replace(Replace(Now(),"/","-"),":",".")sLogFileName = sNow & " - " & sLogFileNamebPrependDateStampInLogFileName = FalseEnd If
sLogFile = sLogFileLocation & sLogFileName
If sOverWriteORAppend = "overwrite" ThenSet oLogFile = oLogFSO.OpenTextFile(sLogFile, ForWriting, True)sOverWriteORAppend = "append"ElseSet oLogFile = oLogFSO.OpenTextFile(sLogFile, ForAppending, True)End If
If bIncludeDateStamp ThenMessage = Now & " " & MessageEnd If
oLogFile.WriteLine(Message)oLogFile.Close
If vLogMaximumLines > 0 ThenSet oReadLogFile = oLogFSO.OpenTextFile(sLogFile, ForReading, True)sFileContents = oReadLogFile.ReadAllaFileContents = Split(sFileContents, vbCRLF)If Ubound(aFileContents) > vLogMaximumLines ThensFileContents = Replace(sFileContents, aFileContents(0) & _vbCRLF, "", 1, Len(aFileContents(0) & vbCRLF))Set oLogFile = oLogFSO.OpenTextFile(sLogFile, ForWriting, True)oLogFile.Write(sFileContents)oLogFile.CloseEnd IfoReadLogFile.CloseEnd If
If vLogMaximumSize > 0 ThenSet oReadLogFile = oLogFSO.OpenTextFile(sLogFile, ForReading, True)sFileContents = oReadLogFile.ReadAlloReadLogFile.ClosesFileContents = RightB(sFileContents, (vLogMaximumSize*2))Set oLogFile = oLogFSO.OpenTextFile(sLogFile, ForWriting, True)oLogFile.Write(sFileContents)oLogFIle.CloseEnd If
oLogFSO = NullEnd Sub
function Ping(byval strName)dim objFSO, objShell, objTempFile, objTSdim sCommand, sReadLinedim bReturn
set objShell = WScript.CreateObject("Wscript.Shell")set objFSO = CreateObject("Scripting.FileSystemObject")
'Set default return valuebReturn = false
'Create command line to ping and save results to a temp filesCommand = "cmd /c ping.exe -n 3 -w 1000 " & strName & " > temp.txt"
'Execute the commandobjShell.run sCommand, 0, true
'Get the temp fileset objTempFile = objFSO.GetFile("temp.txt")set objTS = objTempFile.OpenAsTextStream(1)
'Loop through the temp file to see if "reply from" is found,'if it is then the ping was successfuldo while objTs.AtEndOfStream <> truesReadLine = objTs.ReadLineif instr(lcase(sReadLine), "reply from") > 0 thenbReturn = trueexit doend ifloop
'Close temp file and release objectsobjTS.closeobjTempFile.deleteset objTS = nothingset objTempFile = nothingset objShell = nothingset objFSO = nothing
'Return valuePing = bReturnend function
'---------------- Input Computer Name ---------------------
On Error Resume NextDim strComputerDim intLoopCount, dir, objExcel, objWorkbookSet objExcel = CreateObject("Excel.Application")
'Gets the directory where our script is running fromdir = CreateObject("Scripting.FileSystemObject").GetParentFolderName(Wscript.ScriptFullName)
'Open our EXCEL fileSet objWorkbook = objExcel.Workbooks.Open(dir & "\Computers-Report.xls")
intLoopCount = 1
'Do Until objExcel.Cells(intLoopCount,1).Value = ""Do While Not IsEmpty(objExcel.Cells(loopCount, 1).Value)
strComputer = objExcel.Cells(intLoopCount,1).Value
StrComputer=UCase(StrComputer)
'ping the StrComputer to see if it is accessiblebPingtest = ping(StrComputer)
If bPingtest = FALSE ThenLogToFile "" & strComputer & "Is not accessible. Ping failed."Loop
end IF'''----------------Stop Automatic Updates Service--------------------'''On Error Resume Next' NB strService is case sensitive.strService = " 'wuauserv' "Set objWMIService = GetObject("winmgmts:" _& "{impersonationLevel=impersonate}!\\" _& strComputer & "\root\cimv2")Set colListOfServices = objWMIService.ExecQuery _("Select * from Win32_Service Where Name ="_& strService & " ")For Each objService in colListOfServicesobjService.StopService()Next LogToFile "" & strComputer & "Automatic update service has been stopped."''''----------------Stop BITS Service--------------------'''On Error Resume Next' NB strService is case sensitive.strService = " 'BITS' "Set objWMIService = GetObject("winmgmts:" _& "{impersonationLevel=impersonate}!\\" _& strComputer & "\root\cimv2")Set colListOfServices = objWMIService.ExecQuery _("Select * from Win32_Service Where Name ="_& strService & " ")For Each objService in colListOfServicesobjService.StopService()Next LogToFile "" & strComputer & "Background Intelligent Transfer Service has been stopped"'WScript.Echo "Background Intelligent Transfer Service has been stopped" ''''----------------- Delete Folder and Reg Keys --------------------------------
strExe = "cmd.exe /C rmdir %WINDIR%\SoftwareDistribution /S /Q && cmd.exe /C REG DELETE HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate /f"
' Connect to WMI'set objWMIService = getobject("winmgmts://"_& strComputer & "/root/cimv2")
' Obtain the Win32_Process class of object.
Set objProcess = objWMIService.Get("Win32_Process")Set objProgram = objProcess.Methods_( _"Create").InParameters.SpawnInstance_objProgram.CommandLine = strExe
'Execute the program now at the command line.
Set strShell = objWMIService.ExecMethod( _"Win32_Process", "Create", objProgram)LogToFile "" & strComputer & "The software Distribution Folder and WindowsUpdate regsitry keys have been deleted."'WScript.Echo "The software Distribution Folder and WindowsUpdate regsitry keys have been deleted."
'------------------ Start Automatic Update Service -------------'''On Error Resume Next' NB strService is case sensitive.strService = " 'wuauserv' "Set objWMIService = GetObject("winmgmts:" _& "{impersonationLevel=impersonate}!\\" _& strComputer & "\root\cimv2")Set colListOfServices = objWMIService.ExecQuery _("Select * from Win32_Service Where Name ="_& strService & " ")For Each objService in colListOfServicesobjService.StartService()Next LogToFile "Windows Updates Service has been Started on " & strcomputer 'WScript.Echo "Windows Updates Service has been Started on " & strcomputer '''------------------ Start BITS Service -------------'''On Error Resume Next' NB strService is case sensitive.strService = " 'BITS' "Set objWMIService = GetObject("winmgmts:" _& "{impersonationLevel=impersonate}!\\" _& strComputer & "\root\cimv2")Set colListOfServices = objWMIService.ExecQuery _("Select * from Win32_Service Where Name ="_& strService & " ")For Each objService in colListOfServicesobjService.StartService()Next LogToFile "Background Intelligent Transfer Service has been Started on " & strcomputer 'WScript.Echo "Background Intelligent Transfer Service has been Started on " & strcomputer ''-------------- Force Checking to WSUS server by issueing a wuauclt.exe /resetauthorization /detectnow ------------
strExe = "cmd.exe /C wuauclt.exe /resetauthorization /detectnow"
Set strShell = objWMIService.ExecMethod( _"Win32_Process", "Create", objProgram)LogToFile "" & strComputer & "Force checkin has been sent. Process Complete."'WScript.Echo "Force checkin has been sent. Process Complete."
intLoopCount = intLoopCount + 1
LoopLogToFile "*********************************************************"objExcel.Workbooks.CloseobjExcel.quitobjExcel = EmptyobjWorkbook = Empty
I'm looking forward to the next chalange now.
Posted in Technology | Windows |Comments [0]
The content of this site are my own personal opinions and do not represent my employer's view in anyway.