-
WSUS script help
I've quickly modded our shutdown script to include wsus updates using a wsus script i got somewhere, and mangled them together - does this look ok before i trash everything ? (vbscript is not something i'm totally familiar with)
In theory this should load a .txt file with a list of certain groups of pc's and check for updates, install if neccesary then shutdown.
Code:
Dim oFSO, oTS, sClient, oWindows, oLocator, oConnection, oSys
Dim sUser, sPassword
'set remote credentials
sUser = "***********"
sPassword = "***********"
'open list of client names
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oTS = oFSO.OpenTextFile("C:\Shutdown\test.txt")
Do Until oTS.AtEndOfStream
'get next client name
sClient = oTS.ReadLine
'get WMI locator
Set oLocator = CreateObject("WbemScripting.SWbemLocator")
'Connect to remote WMI
Set oConnection = oLocator.ConnectServer(sClient, _
"root\cimv2", sUser, sPassword)
Set oWindows = oConnection.ExecQuery("Select " & _
"Name From Win32_OperatingSystem")
For Each oSys In oWindows
'ShutdownOption = nForced_Power_Off
'Monthly log;
dt = date() : nMonth = Year(dt)*1e2 + Month(dt)
sLogFile = "C:\WUSforceupdate-" & nMonth & ".log"
Set updateSession = CreateObject("Microsoft.Update.Session")
Set updateSearcher = updateSession.CreateupdateSearcher()
Set searchResult = _
updateSearcher.Search("IsInstalled=0 and Type='Software'")
Set File = CreateObject("Scripting.FileSystemObject")
Set LogFile = File.OpenTextFile(sLogFile, 8, True)
LogFile.WriteLine("***************************************************************")
LogFile.WriteLine( "START TIME : " & now)
LogFile.WriteLine( "Searching for updates..." & vbCRLF)
LogFile.WriteLine( "List of applicable items on the machine:")
For I = 0 To searchResult.Updates.Count-1
Set update = searchResult.Updates.Item(I)
LogFile.WriteLine( I + 1 & "> " & update.Title)
Next
Set WshShell = WScript.CreateObject("WScript.Shell")
If searchResult.Updates.Count = 0 Then
LogFile.WriteLine( "There are no applicable updates.")
'WshShell.popup "There are no applicable updates.",1
'ShutDown(ShutdownOption) '<-- O P T I O N A L
'Wscript.quit
End If
LogFile.WriteLine( vbCRLF & "Creating collection of updates to download:")
Set updatesToDownload = CreateObject("Microsoft.Update.UpdateColl")
For I = 0 to searchResult.Updates.Count-1
Set update = searchResult.Updates.Item(I)
LogFile.WriteLine( I + 1 & "> adding: " & update.Title )
updatesToDownload.Add(update)
Next
LogFile.WriteLine( vbCRLF & "Downloading updates...")
Set downloader = updateSession.CreateUpdateDownloader()
downloader.Updates = updatesToDownload
downloader.Download()
LogFile.WriteLine( vbCRLF & "List of downloaded updates:")
For I = 0 To searchResult.Updates.Count-1
Set update = searchResult.Updates.Item(I)
If update.IsDownloaded Then
LogFile.WriteLine( I + 1 & "> " & update.Title )
End If
Next
Set updatesToInstall = CreateObject("Microsoft.Update.UpdateColl")
LogFile.WriteLine( vbCRLF & _
"Creating collection of downloaded updates to install:" )
For I = 0 To searchResult.Updates.Count-1
set update = searchResult.Updates.Item(I)
If update.IsDownloaded = true Then
'WshShell.popup "installing..." & vbNewLine & update.Title,1
LogFile.WriteLine( I + 1 & "> adding: " & update.Title )
updatesToInstall.Add(update)
End If
Next
logFile.WriteLine( "Installing updates...")
Set installer = updateSession.CreateUpdateInstaller()
installer.Updates = updatesToInstall
Set installationResult = installer.Install()
'Output results of install
LogFile.WriteLine( "Installation Result: " & installationResult.ResultCode )
LogFile.WriteLine( "Reboot Required: " & installationResult.RebootRequired & vbCRLF )
LogFile.WriteLine( "Listing of updates installed " _
& "and individual installation results:" )
For I = 0 to updatesToInstall.Count - 1
LogFile.WriteLine( I + 1 & "> " & updatesToInstall.Item(i).Title _
& ": " & installationResult.GetUpdateResult(i).ResultCode )
Next
If installationResult.RebootRequired = -1 Then
LogFile.WriteLine( "RebootRequired")
' <-- normally now you should call for a R E B O O T.....
End If
'ShutDown(ShutdownOption) '<-- O P T I O N A L
LogFile.WriteLine( "STOP TIME : " & now)
LogFile.WriteLine("***************************************************************")
LogFile.Close
'wscript.echo "Updates are installed"
oSys.Win32ShutDown(12)
Next
Loop
'close the text File
oTS.Close
-
No :-)
If you're running this is a machine shutdown script, why are you trying to read a list of PC names? If this is running at shutdown, surely you only want to check the machine it's currently running on?
the stuff which creates the updatesearcher etc looks fine but it's only going to run on the local machine. The stuff to do the shutdown isn't necessary if you put this as part of your shutdown script - basically, the script should run, install updates and once it quits the normal shutdown process takes over.
If what you want to do is have a script which runs (say) on your machine and forces a batch of machines to check for updates then it's a bit more complex - I don't think there's a way of using WMI to remotely kick off the search for updates process but you could have a script which is copied to the remote machine and then forced to run.
-
Thanks, well at least I know it doesn't work now ;p
The shutdown script, is something thats been on the servers since I started - basically shuts down batches of machines at different times (keeping admin seperate etc)
It reads a text file which has a list of machines and shuts them down via scheduled tasks on the server - it works well.
I was hoping to amalgamate updates and shutdown in one, so as to cause as little user intervention as possible. WSUS is a little summer project for me and so far its been great - but it has not been without problems, e.g. the little yellow shield appearing saying updates are available, and shutdown and install updates on the logon/off screen which has been blocking the shutdown script from working, hence me trying a different approach.
The WSUS script I found works locally, but at the moment I can't think of an easy way to distribute it (heh this was only meant to be a small project ;p).
-
Do you have shutdown scripts configured in active directory for your machines? (this is what I thought you meant by a "shutdown script")
If so, you could put the windows update stuff in there. You might not want it to run every time the machine shuts down, only if it's triggered by the remote shutdown process. One way of doing that would be for the process on the server to write a flag file on the workstation. that's then looked for by the shutdown script; if found, it does the updates and deletes the flag, otherwise it just exits.
In the server side script you would have:
Code:
sClient = oTS.ReadLine
set oFlag=ofso.createtextfile("\\" & sClient & "\c$\wsus.flag",true)
oFlag.writeline "run updates"
oFlag.close
This bit will put a file called C:\wsus.flag on the remote machine
The update script would be basically what you have now but at the start you would do:
Code:
Set File = CreateObject("Scripting.FileSystemObject")
if not file.fileexists("c:\wsus.flag") then wscript.quit
Set LogFile = File.OpenTextFile(sLogFile, 8, True)
- extra line checks for flag and quits if not there.
finally, you need code after the updates are installed to remove the flag:
Code:
logfile.close
if file.fileexists("c:\wsus.flag") then file.deletefile("c:\wsus.flag",true)
and that last line does that.
-
sorry I didnt make it too clear :)
as far as i can tell its this script, that runs via scheduled tasks on the server, different times for different groups
http://www.scriptinganswers.com/vaul...0computers.zip this is the one i mashed together with the wsus script, in the hope that it might work ;p
I've changed the script(s) to your recommendations, however i'm a bit unclear as to where the WSUS script needs to live, sorry to be a n00b ;p
*edit* think i've worked it out !
mark
-
No problem :-)
You need to have a group policy object configured for all your workstations - I don't know how your AD is configured but I'm guessing that you'll have some sort of top level OU under which you have all your desktop PCs and you either have an existing GPO which you can reuse or you can create a new one linked there (for testing it may be easier to have a new one linked to an OU containing just a test PC)
When you edit the GPO you'll see 2 main sections - computer config and user config; you want the first one. Expand that until you see "Windows settings" and then "scripts (Startup/Shutdown)" Click on that and then double click shutdown - you're now looking at the details of scripts which will be run when machines in the OU where this GPO is linked shutdown - I'm guessing there's nothing there.
Click on "Show files" - you'll see a folder where you can put the script you've written. Now click the "Add" button and browse to find your script. OK out of the whole process.
The next time a machine in that OU shuts down it will run your shutdown script - assuming the flag stuff works then actually nothing much will happen. Restart the machine and this time force it to shutdown with your server side script. This time it should process the updates and write its log.
Hope that's clear - it's taken me about an hour to write this because I'm doing about a million other things - but shout if it's not :-)
-
thanks for the help,
That's where i've put it, i've set it up on a test group for tonight and see what happens in the morning, fingers crossed,
I know what you mean about a million other things, same with me!
Thanks again
-
well, didnt work seems there was a problem with the script (cannot use parentheses when calling a sub)
which turned out to be this
Code:
if file.fileexists("c:\wsus.flag") then file.deletefile("c:\wsus.flag",true)
which i changed to (hope its right)
Code:
if file.fileexists("c:\wsus.flag") then file.deletefile("c:\wsus.flag")
all seems to be working however it's not deleting the wsus.flag file ? - doesnt appear to be finishing the log file cleanly either - stops at the entry "Installing updates..."
ill keep playing about with it
mark
-
Sorry - I should never write code from memory (now I'm old it just doesn't work :-))
should be:
Code:
if file.fileexists("c:\wsus.flag") then file.deletefile "c:\wsus.flag", true
(first bit is a function so uses brackets; second bit is a method so doesn't need brackets. The "true" just says "force delete of file" and is probably not necessary)