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 Service
2. Delete the %WINDIR%\softwaredistribution folder
3. Delete the HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate keys and subkeys.
4. Start the Automatic updates Service
5. Send a wuauclt.exe /resetauthorization /detectnow command to sysem
bEnableLogging = True
bIncludeDateStamp = True
bPrependDateStampInLogFileName = False
sLogFileLocation = "relative"
sLogFileName = "errors.txt"
sOverWriteORAppend = "append"
vLogMaximumLines = 0
vLogMaximumSize = 0
Sub LogToFile(Message)
If bEnableLogging = False Then Exit Sub
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Set oLogFSO = CreateObject("Scripting.FileSystemObject")
If sLogFileLocation = "relative" Then
Set oLogShell = CreateObject("Wscript.Shell")
sLogFileLocation = oLogShell.CurrentDirectory & "\"
Set oLogShell = Nothing
End If
If bPrependDateStampInLogFileName Then
sNow = Replace(Replace(Now(),"/","-"),":",".")
sLogFileName = sNow & " - " & sLogFileName
bPrependDateStampInLogFileName = False
End If
sLogFile = sLogFileLocation & sLogFileName
If sOverWriteORAppend = "overwrite" Then
Set oLogFile = oLogFSO.OpenTextFile(sLogFile, ForWriting, True)
sOverWriteORAppend = "append"
Else
Set oLogFile = oLogFSO.OpenTextFile(sLogFile, ForAppending, True)
End If
If bIncludeDateStamp Then
Message = Now & " " & Message
End If
oLogFile.WriteLine(Message)
oLogFile.Close
If vLogMaximumLines > 0 Then
Set oReadLogFile = oLogFSO.OpenTextFile(sLogFile, ForReading, True)
sFileContents = oReadLogFile.ReadAll
aFileContents = Split(sFileContents, vbCRLF)
If Ubound(aFileContents) > vLogMaximumLines Then
sFileContents = Replace(sFileContents, aFileContents(0) & _
vbCRLF, "", 1, Len(aFileContents(0) & vbCRLF))
Set oLogFile = oLogFSO.OpenTextFile(sLogFile, ForWriting, True)
oLogFile.Write(sFileContents)
oLogFile.Close
End If
oReadLogFile.Close
End If
If vLogMaximumSize > 0 Then
Set oReadLogFile = oLogFSO.OpenTextFile(sLogFile, ForReading, True)
sFileContents = oReadLogFile.ReadAll
oReadLogFile.Close
sFileContents = RightB(sFileContents, (vLogMaximumSize*2))
Set oLogFile = oLogFSO.OpenTextFile(sLogFile, ForWriting, True)
oLogFile.Write(sFileContents)
oLogFIle.Close
End If
oLogFSO = Null
End Sub
function Ping(byval strName)
dim objFSO, objShell, objTempFile, objTS
dim sCommand, sReadLine
dim bReturn
set objShell = WScript.CreateObject("Wscript.Shell")
set objFSO = CreateObject("Scripting.FileSystemObject")
'Set default return value
bReturn = false
'Create command line to ping and save results to a temp file
sCommand = "cmd /c ping.exe -n 3 -w 1000 " & strName & " > temp.txt"
'Execute the command
objShell.run sCommand, 0, true
'Get the temp file
set 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 successful
do while objTs.AtEndOfStream <> true
sReadLine = objTs.ReadLine
if instr(lcase(sReadLine), "reply from") > 0 then
bReturn = true
exit do
end if
loop
'Close temp file and release objects
objTS.close
objTempFile.delete
set objTS = nothing
set objTempFile = nothing
set objShell = nothing
set objFSO = nothing
'Return value
Ping = bReturn
end function
'---------------- Input Computer Name ---------------------
On Error Resume Next
Dim strComputer
Dim intLoopCount, dir, objExcel, objWorkbook
Set objExcel = CreateObject("Excel.Application")
'Gets the directory where our script is running from
dir = CreateObject("Scripting.FileSystemObject").GetParentFolderName(Wscript.ScriptFullName)
'Open our EXCEL file
Set 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 accessible
bPingtest = ping(StrComputer)
If bPingtest = FALSE Then
LogToFile "" & 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 colListOfServices
objService.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 colListOfServices
objService.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 colListOfServices
objService.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 colListOfServices
objService.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
Loop
LogToFile "*********************************************************"
objExcel.Workbooks.Close
objExcel.quit
objExcel = Empty
objWorkbook = Empty
I'm looking forward to the next chalange now.