Unattended OS Updates via Windows Update using COMate

Share your advanced PureBasic knowledge/code with the community.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Unattended OS Updates via Windows Update using COMate

Post by SFSxOI »

Recently having a need for an unattended updates install at a remote location without our normal server facilitites available to us but a nice fast internet connection; I needed something to download and install updates from Windows Update without having to visit each of the 150 computers and start up the update wizard, after the modified OS install was completed. I could have started a .vbs script or something as there are plenty around, but I wanted to use a Purebasic and COMate solution (for working with the Windows Update Agent API > http://msdn.microsoft.com/en-us/library ... S.85).aspx) . Of course the finished version i'm using actually has the debug lines left out and i write results to a log file, but for this posted version I left the debug lines in. Thought it might help someone so here it is:

(NOTE: This was tested on Windows Vista only with SP 1. For windows XP you need to install the latest Windows Update Agent first before using. Admin privilages are needed - on Vista this is not an issue because the first account created in a Vista install has the necessary privilages (the first account is an admin privilage account and in my case this was the case because it was a fresh clean install pushed down, however, on XP this is not the case and you need to make sure the account has sufficient privilages on XP before using this.)

Code: Select all

XIncludeFile "COMate.pbi"

Procedure WMIReboot()

Define.COMateObject objWMIService, Reboot_Sys
colREBOOT.COMateEnumObject
strComputer.s = "." 

objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
If objWMIService 
  colREBOOT = objWMIService\CreateEnumeration("ExecQuery('Select * from Win32_OperatingSystem')")
  If colREBOOT 
    Reboot_Sys = colREBOOT\GetNextObject() 
    While Reboot_Sys
      
      Reboot_Sys\Invoke("Reboot()")
      
      Reboot_Sys\Release() 
      Reboot_Sys = colREBOOT\GetNextObject()
    Wend
    colREBOOT\Release() 
  EndIf
  objWMIService\Release()
  Else
      MessageRequester("Error", "RebootInfo")  
EndIf
EndProcedure

Procedure WindowsUpdate_Download_Install() ; downloads and installs updates from Windows Update

Protected updateSession.COMateObject
Protected updateSearcher.COMateObject
Protected searchResult.COMateObject
Protected update.COMateObject
Protected Updates.COMateObject
Protected objItem.COMateObject
Protected updatesToDownload.COMateObject
Protected downloader.COMateObject
Protected DownloadResult.COMateObject
Protected updatesToInstall.COMateObject
Protected installer.COMateObject
Protected installationResult.COMateObject
Protected UpdateResult.COMateObject
Protected objItemToInstall.COMateObject
Protected objUpdateDownloadResult.COMateObject

updateSession = COMate_CreateObject("Microsoft.Update.Session")
updateSearcher = updateSession\GetObjectProperty("CreateUpdateSearcher()")

Debug "********************************************************" + #CRLF$
Debug "Searching for available items from Windows Update..." + #CRLF$
Debug "********************************************************" + #CRLF$

searchResult = updateSearcher\GetObjectProperty("Search('IsInstalled=0')") ; to get all updates for driver and software
;searchResult = updateSearcher\GetObjectProperty("Search('IsInstalled=0 and Type=$0027Software$0027')") ; to get updates for software only
;searchResult = updateSearcher\GetObjectProperty("Search('IsInstalled=0 and Type=$0027Driver$0027')") ; to get updates for drivers only
Updates = searchResult\GetObjectProperty("Updates()")
count = Updates\GetIntegerProperty("Count()")

; if there is just nothing at all
If count = 0
Debug #CRLF$
Debug "***********************" + #CRLF$
;Debug count
Debug Str(count) + "   updates available"
Debug "***********************" + #CRLF$
updateSession\Release()
End
EndIf
; if there is something then we press on....

For I = 0 To count - 1
  
  xfound = xfound
  update = searchResult\GetObjectProperty("Updates()")
  objItem = update\GetObjectProperty("Item('" + Str(I) + "')")
  exclude_download$ = objItem\GetStringProperty("Title()") ; filter
  If FindString(exclude_download$, "Update", 1) > 0 ; filter
  xfound = xfound + 1 ; if it is an update each loop pass we add 1 to xfound
  EndIf
  Debug Str(I + 1) + " >>>   " + objItem\GetStringProperty("Title")
  
Next

; if there were no actual updates we might as well make sure we quit
If count => 1 And xfound = 0
;If count = 0
Debug #CRLF$
Debug "////////////////////////////////////////" + #CRLF$
Debug "No actual updates available"
Debug "////////////////////////////////////////" + #CRLF$
updateSession\Release()
End
EndIf

;////////Collection//////////////
Debug #CRLF$
Debug "**********************************************" + #CRLF$
Debug "Creating collection of updates to download:"
Debug "**********************************************" + #CRLF$
Debug #CRLF$
updatesToDownload = COMate_CreateObject("Microsoft.Update.UpdateColl")

For I = 0 To count - 1
    
    update = searchResult\GetObjectProperty("Updates()")
    objItem = update\GetObjectProperty("Item('" + Str(I) + "')")
    Debug Str(I + 1) + "> adding:   " + objItem\GetStringProperty("Title()")
    index = updatesToDownload\GetIntegerProperty("Add(" + Str(objItem) + " as COMateobject)")

Next
;////////////Downloader//////////////
Debug #CRLF$
Debug "Downloading updates..."
Debug #CRLF$

downloader = updateSession\GetObjectProperty("CreateUpdateDownloader()")
downloader\SetProperty("Updates(" + Str(updatesToDownload) + " as COMateobject)")
DownloadResult = downloader\GetObjectProperty("Download()")

For I = 0 To count - 1
    
    update = searchResult\GetObjectProperty("Updates()")
    objItem = update\GetObjectProperty("Item('" + Str(I) + "')")
    exclude_download$ = objItem\GetStringProperty("Title") ; filter
      objUpdateDownloadResult = DownloadResult\GetObjectProperty("GetUpdateResult(" + Str(I) + ")")
         Select objUpdateDownloadResult\GetIntegerProperty("ResultCode()")
            Case 0
              DownloadResultCode$ = "Download Operation has not started."
            Case 1
              DownloadResultCode$ = "Download Operation is in progress."
            Case 2
              DownloadResultCode$ = "Download Operation completed successfully."
            Case 3
              DownloadResultCode$ = "Download Operation completed, but one or more errors occurred during the operation and the results are potentially incomplete."
            Case 4
              DownloadResultCode$ = "Download Operation failed to complete."
            Case 5
              DownloadResultCode$ = "Download Operation was aborted."
            Default
              DownloadResultCode$ = "Download Operation result could not be determined."
          EndSelect
        If objItem\GetIntegerProperty("IsDownloaded()") <> 0
          Debug Str(I + 1) + ">  " + objItem\GetStringProperty("Title") + "   Download Status:   " + DownloadResultCode$
        EndIf

Next

;/////////Installer///////////////////
;
;
;///install collection
updatesToInstall = COMate_CreateObject("Microsoft.Update.UpdateColl")
Debug #CRLF$
Debug "Creating collection of downloaded updates to install:"
Debug #CRLF$

For I = 0 To count - 1
    
    update = searchResult\GetObjectProperty("Updates()")
    objItem = update\GetObjectProperty("Item('" + Str(I) + "')")
    exclude_download$ = objItem\GetStringProperty("Title") ; filter
      If FindString(exclude_download$, "Update", 1) > 0 ; filter here to keep anything but what we want out of the install collection
      objItem\Invoke("AcceptEula()") ; this accepts the EULA automatically when needed, not all updates need it, mostly addin's
        If objItem\GetIntegerProperty("IsDownloaded()") <> 0
          Debug Str(I + 1) + "> install adding:   " + objItem\GetStringProperty("Title()")
          index = updatesToInstall\GetIntegerProperty("Add(" + Str(objItem) + " as COMateobject)")
        EndIf
      EndIf ; filter
; 
Next
; ;////actual installer   
	Debug "Installing updates..." ; will only install whats in the install collection
	installer = updateSession\GetObjectProperty("CreateUpdateInstaller()")
	installer\SetProperty("Updates(" + Str(updatesToInstall) + " as COMateobject)")
	installcount = updatesToInstall\GetIntegerProperty("Count()")
	countinstalled = installcount - 1
	Debug "Install count is =    " + Str(installcount)
		
	If installcount => 1 ; installcount should be 0 if the FindString(exclude_download$, "Update", 1) filter doesn't find any updates with the word Update.
  	; if installcount is => 1 we go ahead with install command
  	installationResult = installer\GetObjectProperty("Install()")
  	Else
  	Debug "Nothing to install."
  	; if installcount = 0 we don't go any further and just end it
	  End
	EndIf
	
	Select installationResult\GetIntegerProperty("ResultCode()")
    Case 0
      Operation_Result$ = "Operation has not started."
    Case 1
      Operation_Result$ = "Operation is in progress."
    Case 2
      Operation_Result$ = "Operation completed successfully."
    Case 3
      Operation_Result$ = "Operation completed, but one or more errors occurred during the operation and the results are potentially incomplete."
    Case 4
      Operation_Result$ = "Operation failed to complete."
    Case 5
      Operation_Result$ = "Operation was aborted."
    Default
      Operation_Result$ = "Operation result could not be determined."
  EndSelect
  reboot = reboot
	rebootrequired = installationResult\GetIntegerProperty("RebootRequired()")
	If rebootrequired =>1
	reboot = reboot + 1
	EndIf
	
	;Output results of install
	Debug "Installation Result Code: " + Operation_Result$
	Debug "Reboot Required: " + Str(rebootrequired)
	Debug "Listing of updates installed and individual installation results:" 
; 	
	For I = 0 To installcount - 1
	  
	  updatedone = updatedone
	  objItemToInstall = updatesToInstall\GetObjectProperty("Item('" + Str(I) + "')")
    objItemInstall$ = objItemToInstall\GetStringProperty("Title()")
    UpdateResult = installationResult\GetObjectProperty("GetUpdateResult(" + Str(I) + ")")
    OpResult = UpdateResult\GetIntegerProperty("ResultCode()")
    If OpResult = 2
    updatedone = updatedone + 1
    countinstalled = installcount - 1 ; subtract each one as its installed, when 0 all are installed
    Debug "Installs remaining =   " + Str(countinstalled)
    EndIf
    
    Select OpResult
      Case 0
        UpdateOperation_Result$ = "Operation has not started."
      Case 1
        UpdateOperation_Result$ = "Operation is in progress."
      Case 2
        UpdateOperation_Result$ = "Operation completed successfully."
      Case 3
        UpdateOperation_Result$ = "Operation completed, but one or more errors occurred during the operation and the results are potentially incomplete."
      Case 4
        UpdateOperation_Result$ = "Operation failed to complete."
      Case 5
        UpdateOperation_Result$ = "Operation was aborted."
      Default
        UpdateOperation_Result$ = "Operation result could not be determined."
    EndSelect
    Debug Str(I + 1) + "> " + Str(objItemToInstall) + "   " +  objItemInstall$ + "   " + UpdateOperation_Result$
				
	Next
	
updateSession\Release()
updatesToDownload\Release()
updatesToInstall\Release()

;//////////reboot////////////
;uncomment below to use reboot if needed after install
; If reboot => 1 And countinstalled = 0 And updatedone => 1
; Debug "Rebooting computer in 30 seconds"
; Delay(30000)
; WMIReboot()
; EndIf

EndProcedure

NOTE: This was tested on Windows Vista only with SP 1. It was tested under live conditions and sucessfully helped me install the updates for the first batch of the 150 computers this morning which was 47 machines. The compiled app was streamlined into the Vista install in an unattended install and pushed down to each machine by a quickly rigged small on site network setup. All of the updates installed sucessfully and everything works. The above only gets updates which have the word "Update" in their title which it turns out is the naming convention for MS for updates. The use of the word "Update" keeps me from having to deal with add-on's and language packs and i get just the updates needed and nothing else. This posted version is the simplified version, the actual production version does a lot more has a few Windows Update Agent callbacks, more error checking, and reboot routines, but this simplified version is good enough for most use and to get you started.

By default, the above code gets updates that are applicapable to your system language and bits. In other words if your system language is German based it will retrieve updates that are for your language along with the others that are also applicapable for your system. It also will retrieve updates that are x64 specific for those with x64 bit operating systems installed, so there is really no need to filter specifically for language or X64 updates because these will be presented anyway because it only retrieves updates based on your system just like you see if you start up the GUI based Windows Update client and do it yourself manually. But, if you really want to, the above code can be setup to 'filter' for specific updates, drives, or service packs using the Microsoft naming conventions:

Updates
Service Packs
Security Updates
Critical Updates
x64
or languages (English, French, German, Japanese, Spanish, stc...)

For example, if you want to get all updates that are just x64 German system related then just change the filter 'FindString' where: exclude_download$ = objItem\GetStringProperty("Title") (in the above code):

Code: Select all

If FindString(exclude_download$, "Update", 1) > 0 And FindString(exclude_download$, "x64", 1) > 0 And FindString(exclude_download$, "German", 1) > 0

(although just getting updates that are specifically for x64 is not a good idea because there are updates that are agnostic bit wise and are for both x64 and x86 and don't reflect that in their naming.)
If you want to get just the Critical or Security related updates, then you would do this:

Code: Select all

FindString(exclude_download$, "Critical", 1) > 0
FindString(exclude_download$, "Security", 1) > 0
If you just want Service Packs:

Code: Select all

FindString(exclude_download$, "Service Pack", 1) > 0

Note: For Service Packs its important to do "Service Pack" and not just "Service" or "Pack" because its possible those words could be included individually in the title for other optional things you might not want, like for example...language packs also include the word "Pack" (but don't include the word "Service"

If just want updates for Media Center:

Code: Select all

If FindString(exclude_download$, "Update", 1) > 0 And FindString(exclude_download$, "Media Center", 1) > 0

Note: Like for Service Packs above its important to do "Media Center" and not just "Media" or "Center" because its possible those words could be included individually in the title for other optional updates you might not want.

You have to change all occurances of the FindString filter above to what you want.

Also, the above gets updates that are not already installed on your system, if for some reason you want to get the updates again change all occurances of 'IsInstalled=0' to 'IsInstalled=1'. But, if you do this these 'duplicate' updates won't install if the system thinks the update is already installed so you will need to add this to force them to install again:

Code: Select all

In the Installer section of the code find this: 

If installcount => 1 ; installcount should be 0 if the FindString(exclude_download$, "Update", 1) filter doesn't find any updates with the word Update. 
   ; if installcount is => 1 we go ahead with install command 
   installationResult = installer\GetObjectProperty("Install()") 
   Else 
   Debug "Nothing to install." 
   ; if installcount = 0 we don't go any further and just end it 
   End 
   EndIf 

And change the area With installationResult = installer\GetObjectProperty("Install()") To this: 

If installcount => 1 ; installcount should be 0 if the FindString(exclude_download$, "Update", 1) filter doesn't find any updates with the word Update. 
   ; if installcount is => 1 we go ahead with install command 
                installer\SetProperty("Install('" + Str(#VARIANT_TRUE) + "')") 
                installationResult = installer\GetObjectProperty("Install()") 
                installer\SetProperty("Install('" + Str(#VARIANT_TRUE) + "')") 
   Else 
   Debug "Nothing to install." 
   ; if installcount = 0 we don't go any further and just end it 
   End 
   EndIf
Last edited by SFSxOI on Wed Mar 18, 2009 8:36 pm, edited 26 times in total.
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Looks nice.

Will need to study a bit :) Nice tutorial.

cheers
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

In the case of computers not connected to the internet you can still update via the off line method. You could also update machines on a closed network without internet access. Here is what a simplified working version looks like:

Code: Select all

Protected updateSession.COMateObject 
Protected updateSearcher.COMateObject 
Protected searchResult.COMateObject 
Protected update.COMateObject 
Protected Updates.COMateObject 
Protected objItem.COMateObject 
Protected UpdateServiceManager.COMateObject 
Protected UpdateService.COMateObject 
  
; needs you to download wsusscan.cab http://go.microsoft.com/fwlink/?LinkId=40751 
; and place it in path shown in wsusscan_cab$ 
; path can also be a local server without internet access 
; latest .cab is always at the url above
; wsusscan_cab$ only contains updates, no add ons or other stuff 

updateSession = COMate_CreateObject("Microsoft.Update.Session")
UpdateServiceManager = COMate_CreateObject("Microsoft.Update.ServiceManager")
updateSearcher = updateSession\GetObjectProperty("CreateUpdateSearcher()")
Offline_Sync_service$ = "Offline Sync Service" 
wsusscan_cab$ = "c:\temp\wsusscan.cab" ; put actual path to .cab 

UpdateService = UpdateServiceManager\GetObjectProperty("AddScanPackageService('" + Offline_Sync_service$ + "', '" + wsusscan_cab$ + "', '" + Str(1) + "')") 
Debug "Searching for updates..." 

updateSearcher\SetProperty("ServerSelection('" + Str(3) + "')") ;  3 is ssOthers, is local machine
UpdateServiceServiceID$ = UpdateService\GetStringProperty("ServiceID()")
updateSearcher\SetProperty("ServiceID('" + UpdateServiceServiceID$ + "')")

searchResult = updateSearcher\GetObjectProperty("Search('IsInstalled=0')") ; to get all updates for driver and software
;searchResult = updateSearcher\GetObjectProperty("Search('IsInstalled=0 and Type=$0027Software$0027')") ; to get updates for software only 
;searchResult = updateSearcher\GetObjectProperty("Search('IsInstalled=0 and Type=$0027Driver$0027')") ; to get updates for drivers only

Updates = searchResult\GetObjectProperty("Updates()")
count = Updates\GetIntegerProperty("Count()")

If count = 0 
Debug "There are no applicable updates."
updateSession\Release()
UpdateServiceManager\SetProperty("RemoveService('" + UpdateServiceServiceID$ + "')") ; see special note below
UpdateService\Release() 
UpdateServiceManager\Release() 
End 
EndIf 

Debug "List of applicable items on the machine when using wssuscan.cab:" 

For I = 0 To count-1 
    update = searchResult\GetObjectProperty("Updates()")
    objItem = update\GetObjectProperty("Item('" + Str(I) + "')")
    Debug Str(I + 1) + " >>>   " + objItem\GetStringProperty("Title()")
Next

;;; add installer section starting here from first post to build install collection and install. Remember to make the applicapable changes.


special note: You must set 'RemoveService' below this before releasing UpdateService

UpdateServiceManager\SetProperty("RemoveService('" + UpdateServiceServiceID$ + "')")

;Failure to call the above RemoveService before releasing the UpdateService causes a resource leak.

Last edited by SFSxOI on Wed Mar 18, 2009 8:37 pm, edited 4 times in total.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Updated code in first post to correct a bug due to something I left out from a copy and paste mistake when I posted it (but was in my working code - sorry 'bout that), added download results cause someone might want it. Also added the reboot method with WMI.

Also corrected the code in the offline update method in the third post due to posting the wrong code - I had multiple PB tabs and clicked on wrong one, sorry.

Now, how to deal with Bundled Updates? Bundled Updates are basically multiple updates combined into in a single update file download. These are things like the rollup updates and service packs. Service packs are a little different though as service packs generally contain their own installer for the most part where as something like a rollup update might not contain its own installer and will depend on the Windows Update Agent to install them. For service packs its different because the Windows Update Agent just mostly invokes the service pack installer and after that the individual updates in the service pack are installed and don't rely on the Windows Update Agent installer to install them individually where something like a rollup update will need the Windows Update Agent installer. Bundled updates are installed individually, the updates contained in the bundle are extracted and installed one at a time by the Windows Update Agent installer, except for service packs where its own installer takes care of that. Because they are extracted and installed individually your update code might need to know whats in them so they can be extracted and installed. The Windows Update Agent in Vista seems to take care of this automatically without further coding using the code posted but XP systems might need to expose the individual updates in a bundle before they can be installed.

Anyway, heres the basic method to handle Bundled Updates, although with the above posted code you shouldn't really need it (on some XP systems a bundled update using the posted methods will throw you some exceptions, this doesn't happen on Vista systems). Its easy to add if you want it or need it.

Basically; To see what individual updates are in a bundled update you just add the below in the search portion of the above code in the For:Next loop in that section, The below is for seeing whats in a bundled update:

(Note: this is a refined version of the Bundled Update previously posted code with the below method being more useful and explainatory)

Code: Select all

;;;add BundledUpdate - break down a bundeled update and see contents
 objBundledUpdates = objItem\GetObjectProperty("BundledUpdates()")
For I = 0 To objBundledUpdates\GetIntegerProperty("Count") - 1
objUpdateBundle$ = objBundledUpdates\GetStringProperty("Item('" + Str(I) + "')")
Debug objUpdateBundle$
Next
  ;;;;end BundledUpdate
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Here is a complete version/application showing use of just about everything. The below just gets operating system updates the way its configured right now but thats easy to change.

Code: Select all

Procedure WMIWrite_to_File_Updates(path_name_of_file.s, string_to_write.s)

Define.COMateObject objFSO, MyFile

ForReading$ = Str(1)
ForWriting$ = Str(2)
ForAppending$ = Str(8)
stringtowrite$ = string_to_write
filetowrite$ = path_name_of_file

objFSO = COMate_CreateObject("Scripting.FileSystemObject")
If objFSO

MyFile = objFSO\GetObjectProperty("OpenTextFile('" + filetowrite$ + "', '" + ForAppending$ + "')")
MyFile\Invoke("WriteLine('" + stringtowrite$ + "')")
MyFile\Invoke("Close()")

EndIf

objFSO\Release()
EndProcedure

Procedure.s WMIRebootx()

Define.COMateObject objWMIService, Reboot_Sys
colREBOOT.COMateEnumObject
strComputer.s = "." 

objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
If objWMIService 
  colREBOOT = objWMIService\CreateEnumeration("ExecQuery('Select * from Win32_OperatingSystem')")
  If colREBOOT 
    Reboot_Sys = colREBOOT\GetNextObject() 
    While Reboot_Sys
      
      Reboot_Sys\Invoke("Reboot()")
      
      Reboot_Sys\Release() 
      Reboot_Sys = colREBOOT\GetNextObject()
    Wend
    colREBOOT\Release() 
  EndIf
  objWMIService\Release()
  Else
      MessageRequester("Error", "RebootInfo")  
EndIf
EndProcedure

Procedure.s WMIShutdownx()

Define.COMateObject objWMIService, Shutdown_Sys
colSHUTDOWN.COMateEnumObject
strComputer.s = "." 

objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
If objWMIService 
  colSHUTDOWN = objWMIService\CreateEnumeration("ExecQuery('Select * from Win32_OperatingSystem')")
  If colSHUTDOWN 
    Shutdown_Sys = colSHUTDOWN\GetNextObject() 
    While Shutdown_Sys
      
      Shutdown_Sys\Invoke("Shutdown()")
      
      Shutdown_Sys\Release() 
      Shutdown_Sys = colSHUTDOWN\GetNextObject()
    Wend
    colSHUTDOWN\Release() 
  EndIf
  objWMIService\Release()
  Else
      MessageRequester("Error", "ShutdownInfo")  
EndIf
EndProcedure

Procedure.i WMIIf_File_Existsx(file_to_check.s) ; where file_to_check.s = full path to the file i.e.. C:\temp\testfile.txt
; returns -1 if the file exists and 0 if it doesn't exist
Define.COMateObject objFSO, MyFile

objFSO = COMate_CreateObject("Scripting.FileSystemObject")
If objFSO

exists.i = objFSO\GetIntegerProperty("FileExists('" + file_to_check + "')")

EndIf

objFSO\Release()
ProcedureReturn exists
EndProcedure

Procedure WindowsUpdate_Download_InstallExx() ; stuffed version - downloads and installs updates from Windows Update

; IUpdate/session objects
Protected updateSession.COMateObject
Protected updateSearcher.COMateObject
Protected searchResult.COMateObject
Protected update.COMateObject
Protected Updates.COMateObject
Protected objItem.COMateObject
; downloader objects
Protected updatesToDownload.COMateObject
Protected downloader.COMateObject
Protected DownloadResult.COMateObject
;installer objects
Protected updatesToInstall.COMateObject
Protected installer.COMateObject
Protected installationResult.COMateObject
Protected UpdateResult.COMateObject
Protected objItemToInstall.COMateObject
Protected objUpdateDownloadResult.COMateObject
; informational objects
Protected objIUpdateIdentity.COMateObject
Protected objCategories.COMateObject
Protected objICategoryItem.COMateObject
Protected objKBStringCollection.COMateObject
Protected objInstallationBehavior.COMateObject
Protected objSecurityBulletinIDs.COMateObject
Protected objSupersededUpdateIDs.COMateObject
Protected objMoreInfoUrls.COMateObject
Protected objUninstallationSteps.COMateObject
Protected objUpdateExceptionCollection.COMateObject
Protected objUpdateExceptionItem.COMateObject
Protected objBundledUpdates.COMateObject
Protected objUpdateLanguage.COMateObject

path_write_file$ = "C:\WUP_Info.txt" 

updateSession = COMate_CreateObject("Microsoft.Update.Session")
updateSearcher = updateSession\GetObjectProperty("CreateUpdateSearcher()")

WMIWrite_to_File_Updates(path_write_file$, "******************************************************************" + #CRLF$)
WMIWrite_to_File_Updates(path_write_file$, "Searching for available items from Windows Update..." + #CRLF$)
WMIWrite_to_File_Updates(path_write_file$, "******************************************************************" + #CRLF$)

;updateSearcher\SetProperty("Online('" + Str(#VARIANT_TRUE) + "')") ; Set to VARIANT_TRUE for the UpdateSearcher to go online; otherwise, VARIANT_FALSE
; VARIANT_FALSE < default = don't need to include this line for windows update - not used here - future for WSUS use and others

searchResult = updateSearcher\GetObjectProperty("Search('IsInstalled=0')") ; to get all updates for driver and software not already installed
;searchResult = updateSearcher\GetObjectProperty("Search('IsInstalled=1 and Type=$0027Software$0027')") ; to get updates for software only
;searchResult = updateSearcher\GetObjectProperty("Search('IsInstalled=0 and Type=$0027Driver$0027')") ; to get updates for drivers only
Updates = searchResult\GetObjectProperty("Updates()")
count = Updates\GetIntegerProperty("Count()")

; if there is just nothing at all
If count = 0
WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
WMIWrite_to_File_Updates(path_write_file$, "************************************************" + #CRLF$)
WMIWrite_to_File_Updates(path_write_file$, Str(count) + "   updates available")
WMIWrite_to_File_Updates(path_write_file$, "************************************************" + #CRLF$)
updateSession\Release()
End
EndIf
; if there is something then we press on....

For X = 0 To count - 1
  
  xfound = xfound
  update = searchResult\GetObjectProperty("Updates()")
  objItem = update\GetObjectProperty("Item('" + Str(X) + "')")
  
  objIUpdateIdentity = objItem\GetObjectProperty("Identity()")
  UpdateID$ = objIUpdateIdentity\GetStringProperty("UpdateID()")
  Select objItem\GetIntegerProperty("Type()")
    Case 1
      IUpdateType$ = "Software"
    Case 2
      IUpdateType$ = "Driver"
  EndSelect
  MsrcSeverity$ = objItem\GetStringProperty("MsrcSeverity()")
    UpdateDescription$ = objItem\GetStringProperty("Description()")
      RecommendedMemory = objItem\GetIntegerProperty("RecommendedMemory()")
        MaxDownloadSize = objItem\GetIntegerProperty("MaxDownloadSize()")
            SupportUrl$ = objItem\GetStringProperty("SupportUrl()")
              RecommendedHardDiskSpace = objItem\GetIntegerProperty("RecommendedHardDiskSpace()")
            UninstallationNotes$ = objItem\GetStringProperty("UninstallationNotes()")
        MinDownloadSize = objItem\GetIntegerProperty("MinDownloadSize()")
      RecommendedCPUSpeed = objItem\GetIntegerProperty("RecommendedCPUSpeed()")
    RecommendedMemory = objItem\GetIntegerProperty("RecommendedMemory()")
  exclude_download$ = objItem\GetStringProperty("Title()") ; filter
  DeploymentChangeTime$ = objItem\GetStringProperty("LastDeploymentChangeTime()")
  
    If objItem\GetIntegerProperty("CanRequireSource()") = 0
        RequireSource$ = "Source media of the update is not required for installation or uninstallation."
      Else
        RequireSource$ = "Source media of the update is required for installation or uninstallation."
    EndIf
    
    If objItem\GetIntegerProperty("IsBeta()") = 0
        IsBeta$ = "This is not a beta update release."
      Else
        IsBeta$ = "This is a beta update release."
    EndIf
    
    If objItem\GetIntegerProperty("IsMandatory()") = 0
    Mandatory$ = "This update is not a mandatory update for the Windows Update Agent (WUA) infrastructure."
    Else
    Mandatory$ = "This update is a mandatory update for the Windows Update Agent (WUA) infrastructure."
    EndIf
      
    Select objItem\GetIntegerProperty("DeploymentAction()")
      Case 0
        DeployAction$ = "None - No explicit deployment action is specified on the update. The update inherits the action from its bundled updates."
      Case 1
        DeployAction$ = "Installation - The update should be installed on the computer and/or for the specified user."
      Case 2
        DeployAction$ = "Uninstallation - The update should be uninstalled from the computer and/or for the specified user."
      Case 3
        DeployAction$ = "Detection - The update is deployed only to determine the applicability of the update. The update will not be installed."
    EndSelect
    
    If objItem\GetIntegerProperty("IsUninstallable()") = 0
    IsUninstallable$ = "False"
    Else
    IsUninstallable$ = "True"
    EndIf
    
    ; install behavior info
    objInstallationBehavior = objItem\GetObjectProperty("InstallationBehavior()")
    If objInstallationBehavior\GetIntegerProperty("RequiresNetworkConnectivity()") = 0
        RequiresNetworkConnectivity$ = "False - The update does not require network connectivity for installation or uninstallation."
      Else
        RequiresNetworkConnectivity$ = "True - The update does require network connectivity for installation or uninstallation."
    EndIf
       
    If objInstallationBehavior\GetIntegerProperty("CanRequestUserInput()") = 0
        CanRequestUserInput$ = "The installation or uninstallation of this update does not prompt for user input."
      Else
        CanRequestUserInput$ = "The installation or uninstallation of this update can prompt for user input."
    EndIf
     
    Select objInstallationBehavior\GetIntegerProperty("RebootBehavior()")
      Case 0
        RebootBehavior$ = "The update never requires a system restart during or after an installation or an uninstallation."
      Case 1
        RebootBehavior$ = "The update always requires a system restart after a successful installation or uninstallation."
      Case 2
        RebootBehavior$ = "The update can request a system restart after a successful installation or uninstallation."
    EndSelect
    
  ;filter by update indication in update name to get updates found count
  If FindString(exclude_download$, "Update", 1) > 0 ; filter
  xfound = xfound + 1 ; if it is an update each loop pass we add 1 to xfound
  EndIf
  
  ; results to file
  WMIWrite_to_File_Updates(path_write_file$, "Available Windows Update Item #  " + Str(X + 1) + " >>>   " + objItem\GetStringProperty("Title") + "    Update ID =  " + UpdateID$)
  
  objBundledUpdates = objItem\GetObjectProperty("BundledUpdates()")
  a = 1
  For I = 0 To objBundledUpdates\GetIntegerProperty("Count") - 1
    a = a
      objUpdateBundle$ = objBundledUpdates\GetStringProperty("Item('" + Str(I) + "')")
      WMIWrite_to_File_Updates(path_write_file$, "Bundled Update  > " + Str(a) + " =   " + objUpdateBundle$)
    a = a + 1
  Next
  
  objCategories = objItem\GetObjectProperty("Categories()")
  For Z = 0 To objCategories\GetIntegerProperty("Count") - 1
  objICategoryItem = objCategories\GetObjectProperty("Item('" + Str(Z) + "')")
    CategoryName$ = objICategoryItem\GetStringProperty("Name()")
    WMIWrite_to_File_Updates(path_write_file$, "Category Name   >  " + CategoryName$)
    CategoryID$ = objICategoryItem\GetStringProperty("CategoryID()")
    WMIWrite_to_File_Updates(path_write_file$, "Category ID   >  " + CategoryID$)
    CategoryDescription$ = objICategoryItem\GetStringProperty("Description()")
    WMIWrite_to_File_Updates(path_write_file$, "Category Description   >  " + CategoryDescription$)
    CategoryType$ = objICategoryItem\GetStringProperty("Type()")
    WMIWrite_to_File_Updates(path_write_file$, "Category Type   >  " + CategoryType$)
  Delay(1)
  Next
  
  WMIWrite_to_File_Updates(path_write_file$, "Update Description   >  " + UpdateDescription$)
  WMIWrite_to_File_Updates(path_write_file$, "Publish Date   >  " + DeploymentChangeTime$)
  WMIWrite_to_File_Updates(path_write_file$, "Update Type   >  " + IUpdateType$)
  WMIWrite_to_File_Updates(path_write_file$, "Category Name   >  " + CategoryName$)

  objUpdateLanguage = objItem\GetObjectProperty("Languages()")
  For I = 0 To objUpdateLanguage\GetIntegerProperty("Count") - 1
  UpdateLanguage$ = objUpdateLanguage\GetStringProperty("Item(" + Str(I) + ")")
    WMIWrite_to_File_Updates(path_write_file$, "Language Supported   >  " + UpdateLanguage$)
    Delay(1)
  Next
  
  WMIWrite_to_File_Updates(path_write_file$, "Support Url   >  " + SupportUrl$)
  objMoreInfoUrls = objItem\GetObjectProperty("MoreInfoUrls()")
  For I = 0 To objMoreInfoUrls\GetIntegerProperty("Count") - 1
  objMoreInfoUrls$ = objMoreInfoUrls\GetStringProperty("Item(" + Str(I) + ")")
    WMIWrite_to_File_Updates(path_write_file$, "More Info Urls   >  " + objMoreInfoUrls$)
    Delay(1)
  Next
  
  WMIWrite_to_File_Updates(path_write_file$, "Requires Network Connectivity ?   >  " + RequiresNetworkConnectivity$)
  WMIWrite_to_File_Updates(path_write_file$, "Does Update Request User Input ?   >  " + CanRequestUserInput$)
  WMIWrite_to_File_Updates(path_write_file$, "Reboot Behavior ?   >  " + RebootBehavior$)
  
  If FindString(objItem\GetStringProperty("Title"), "Language Pack", 1) = 0 ; language packs don't have real KB ID's so we don't waste time writing the KB ID for them
  ;If FindString(objItem\GetStringProperty("Title"), "Update", 1) => 1 ; if we only need KB articles for actual updates
  objKBStringCollection = objItem\GetObjectProperty("KBArticleIDs()")
  For I = 0 To objKBStringCollection\GetIntegerProperty("Count") - 1
  objKBStringItem$ = objKBStringCollection\GetStringProperty("Item(" + Str(I) + ")")
    WMIWrite_to_File_Updates(path_write_file$, "KB Article ID   >  " + objKBStringItem$)
    If objKBStringItem$ <> ""
    WMIWrite_to_File_Updates(path_write_file$, "KB Article URL   >  " + "http://support.microsoft.com/kb/" + objKBStringItem$)
    EndIf
    Delay(1)
  Next
  EndIf 
  
  objSecurityBulletinIDs = objItem\GetObjectProperty("SecurityBulletinIDs()")
  For I = 0 To objSecurityBulletinIDs\GetIntegerProperty("Count") - 1
  objSecurityBulletinIDs$ = objSecurityBulletinIDs\GetStringProperty("Item(" + Str(I) + ")")
    If Len(objSecurityBulletinIDs$) = 0
      WMIWrite_to_File_Updates(path_write_file$, "Security Bulletin ID   >  " + "Information not available for this update.")
    Else
      WMIWrite_to_File_Updates(path_write_file$, "Security Bulletin ID   >  " + objSecurityBulletinIDs$)
    EndIf
    Delay(1)
  Next
  
  objSupersededUpdateIDs = objItem\GetObjectProperty("SupersededUpdateIDs()")
  For I = 0 To objSupersededUpdateIDs\GetIntegerProperty("Count") - 1
  objSupersededUpdateIDs$ = objSupersededUpdateIDs\GetStringProperty("Item(" + Str(I) + ")")
    If Len(objSupersededUpdateIDs$) = 0
      WMIWrite_to_File_Updates(path_write_file$, "Superseded Update ID   >  " + "Information not available for this update.")
    Else
      WMIWrite_to_File_Updates(path_write_file$, "Superseded Update ID   >  " + objSupersededUpdateIDs$)
    EndIf
    Delay(1)
  Next
  
  If Len(MsrcSeverity$) = 0
    WMIWrite_to_File_Updates(path_write_file$, "MSRC Severity   >  " + "Information not available for this update.")
  Else
    WMIWrite_to_File_Updates(path_write_file$, "MSRC Severity   >  "  + MsrcSeverity$)
  EndIf
  
  WMIWrite_to_File_Updates(path_write_file$, "Source Required ?   >  " + RequireSource$)
  WMIWrite_to_File_Updates(path_write_file$, "Is update a beta release ?   >  " + IsBeta$)
  WMIWrite_to_File_Updates(path_write_file$, "Is Mandatory ?   >  " + Mandatory$)
  WMIWrite_to_File_Updates(path_write_file$, "Deployment Action   >  " + DeployAction$)
  WMIWrite_to_File_Updates(path_write_file$, "Max Download Size   >  " + Str(MaxDownloadSize) + "  Kb")
  WMIWrite_to_File_Updates(path_write_file$, "Min Download Size   >  " + Str(MinDownloadSize) + "  Kb")

  If RecommendedCPUSpeed = 0
      WMIWrite_to_File_Updates(path_write_file$, "Recommended CPU Speed   >  " + "Information not available for this update.")
    Else
      WMIWrite_to_File_Updates(path_write_file$, "Recommended CPU Speed   >  " + Str(RecommendedCPUSpeed) + "  Mhz")
  EndIf
  If RecommendedHardDiskSpace = 0
      WMIWrite_to_File_Updates(path_write_file$, "Recommended Hard Disk Space   >  " + "Information not available for this update.")
    Else
      WMIWrite_to_File_Updates(path_write_file$, "Recommended Hard Disk Space   >  " + Str(RecommendedHardDiskSpace) + "  MB")
  EndIf
  If RecommendedMemory = 0
      WMIWrite_to_File_Updates(path_write_file$, "Recommended Memory   >  " + "Information not available for this update.")
    Else
      WMIWrite_to_File_Updates(path_write_file$, "Recommended Memory   >  " + Str(RecommendedMemory) + "  MB")
  EndIf
  
  WMIWrite_to_File_Updates(path_write_file$, "Uninstallable ?   >  " + IsUninstallable$)
  WMIWrite_to_File_Updates(path_write_file$, "Uninstallation Notes   >   " + UninstallationNotes$)
  
  objUninstallationSteps = objItem\GetObjectProperty("UninstallationSteps()")
  c = 1
  For I = 0 To objUninstallationSteps\GetIntegerProperty("Count") - 1
  objUninstallationSteps$ = objUninstallationSteps\GetStringProperty("Item(" + Str(I) + ")")
  WMIWrite_to_File_Updates(path_write_file$, "Uninstallation Steps :")
  WMIWrite_to_File_Updates(path_write_file$, Str(c) + ". >  " + objUninstallationSteps$)
  c = c + 1
  Delay(1)
  Next
  WMIWrite_to_File_Updates(path_write_file$, "************************************************")
  WMIWrite_to_File_Updates(path_write_file$, "************************************************")

Delay(1)
Next ; end I loop

  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "/////////////////////////////////////////////////" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "Number of applicapable updates found =   " + Str(xfound))
  WMIWrite_to_File_Updates(path_write_file$, "/////////////////////////////////////////////////" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)

we can filter here And stop it now If no updates
If there were no actual updates we might As well make sure we quit
If count => 1 And xfound = 0

  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "/////////////////////////////////////////////////" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "No actual updates available")
  WMIWrite_to_File_Updates(path_write_file$, "/////////////////////////////////////////////////" + #CRLF$)

updateSession\Release()
End
EndIf

; ;////////Download Collection//////////////
  
  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "******************************************************************" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "Creating collection of updates to download...")
  WMIWrite_to_File_Updates(path_write_file$, "******************************************************************" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)

updatesToDownload = COMate_CreateObject("Microsoft.Update.UpdateColl")

For I = 0 To count - 1
    
    update = searchResult\GetObjectProperty("Updates()")
    objItem = update\GetObjectProperty("Item('" + Str(I) + "')")
    WMIWrite_to_File_Updates(path_write_file$, Str(I + 1) + "> Adding to download collection:   " + objItem\GetStringProperty("Title()"))
    index = updatesToDownload\GetIntegerProperty("Add(" + Str(objItem) + " as COMateobject)")

Delay(1)
Next

; ;////////////Downloader//////////////
 
  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "******************************************************************" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "Downloading updates...")
  WMIWrite_to_File_Updates(path_write_file$, "******************************************************************" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)

downloader = updateSession\GetObjectProperty("CreateUpdateDownloader()")
downloader\SetProperty("Updates(" + Str(updatesToDownload) + " as COMateobject)")
DownloadResult = downloader\GetObjectProperty("Download()")

For I = 0 To count - 1
    
    update = searchResult\GetObjectProperty("Updates()")
    objItem = update\GetObjectProperty("Item('" + Str(I) + "')")
    objUpdateDownloadResult = DownloadResult\GetObjectProperty("GetUpdateResult(" + Str(I) + ")")
         Select objUpdateDownloadResult\GetIntegerProperty("ResultCode()")
            Case 0
              DownloadResultCode$ = "Download Operation has not started."
            Case 1
              DownloadResultCode$ = "Download Operation is in progress."
            Case 2
              DownloadResultCode$ = "Download Operation completed successfully."
            Case 3
              DownloadResultCode$ = "Download Operation completed, but one or more errors occurred and results are potentially incomplete."
            Case 4
              DownloadResultCode$ = "Download Operation failed to complete."
            Case 5
              DownloadResultCode$ = "Download Operation was aborted."
            Default
              DownloadResultCode$ = "Download Operation result could not be determined."
          EndSelect
        If objItem\GetIntegerProperty("IsDownloaded()") <> 0
          WMIWrite_to_File_Updates(path_write_file$, Str(I + 1) + ">  " + objItem\GetStringProperty("Title") + "   Download Status:   " + DownloadResultCode$)
        EndIf
Delay(1)
Next

;/////////Installer///////////////////
; 
; ;///install collection
updatesToInstall = COMate_CreateObject("Microsoft.Update.UpdateColl")

  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "******************************************************************" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "Creating collection of downloaded updates to install:")
  WMIWrite_to_File_Updates(path_write_file$, "******************************************************************" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)

For I = 0 To count - 1
    
    update = searchResult\GetObjectProperty("Updates()")
    objItem = update\GetObjectProperty("Item('" + Str(I) + "')")
    exclude_download$ = objItem\GetStringProperty("Title") ; filter
      If FindString(exclude_download$, "Update", 1) > 0 ; filter here to keep anything but what we want out of the install collection
      objItem\Invoke("AcceptEula()") ; this accepts the EULA automatically when needed, not all updates need it, mostly addin's
        If objItem\GetIntegerProperty("IsDownloaded()") <> 0
          WMIWrite_to_File_Updates(path_write_file$, Str(I + 1) + "> Adding to install collection:   " + objItem\GetStringProperty("Title()"))
          index = updatesToInstall\GetIntegerProperty("Add(" + Str(objItem) + " as COMateobject)")
        EndIf
      EndIf ; filter
Delay(1)
Next
; ;////actual installer   
;Installing updates...will only install whats in the install collection
	
  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "******************************************************************" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "Installing updates...")
  WMIWrite_to_File_Updates(path_write_file$, "******************************************************************" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)

	installer = updateSession\GetObjectProperty("CreateUpdateInstaller()")
	installer\SetProperty("Updates(" + Str(updatesToInstall) + " as COMateobject)")
	installcount = updatesToInstall\GetIntegerProperty("Count()")
	countinstalled = installcount - 1
	
  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "/////////////////////////////////////////////////////////////////" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "Install count is =    " + Str(installcount))
  WMIWrite_to_File_Updates(path_write_file$, "/////////////////////////////////////////////////////////////////" + #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
	
	If installcount => 1 ; installcount should be 0 if the FindString(exclude_download$, "Update", 1) filter doesn't find any updates with the word Update.
  	; if installcount is => 1 we go ahead with install command
  	installationResult = installer\GetObjectProperty("Install()") ; this will invoke actual install action
  	Else
    	WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
      WMIWrite_to_File_Updates(path_write_file$, "//////////////////////////////////" + #CRLF$)
      WMIWrite_to_File_Updates(path_write_file$, "Nothing to install.")
      WMIWrite_to_File_Updates(path_write_file$, "//////////////////////////////////" + #CRLF$)
      WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
      updateSession\Release()
      updatesToDownload\Release()
      updatesToInstall\Release()
  	; if installcount = 0 we don't go any further and just end it
	  End
	EndIf
	
	Select installationResult\GetIntegerProperty("ResultCode()")
    Case 0
      Operation_Result$ = "Operation has not started."
    Case 1
      Operation_Result$ = "Operation is in progress."
    Case 2
      Operation_Result$ = "Operation completed successfully."
    Case 3
      Operation_Result$ = "Operation completed, but one or more errors occurred and results are potentially incomplete."
    Case 4
      Operation_Result$ = "Operation failed to complete."
    Case 5
      Operation_Result$ = "Operation was aborted."
    Default
      Operation_Result$ = "Operation result could not be determined."
  EndSelect
  reboot = reboot
	rebootrequired = installationResult\GetIntegerProperty("RebootRequired()")
	If rebootrequired =>1
	reboot = reboot + 1
	reboot_required$ = "Computer reboot is required."
	Else
	reboot_required$ = "Computer reboot is not required."
	EndIf
	
	;Output results of install
	
  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
  WMIWrite_to_File_Updates(path_write_file$, "------------------------ Installation Results ------------------------")
  WMIWrite_to_File_Updates(path_write_file$, "-----------------------------------------------------------------")
  WMIWrite_to_File_Updates(path_write_file$, "Installation Result Code: " + Operation_Result$)
  WMIWrite_to_File_Updates(path_write_file$, "Reboot Required ? :  " + reboot_required$)
  WMIWrite_to_File_Updates(path_write_file$, "-----------------------------------------------------------------")
  WMIWrite_to_File_Updates(path_write_file$, "Listing of updates installed and individual installation results:")
  WMIWrite_to_File_Updates(path_write_file$, "-----------------------------------------------------------------")
  WMIWrite_to_File_Updates(path_write_file$, #CRLF$)
	
	For I = 0 To installcount - 1
	  
	  updatedone = updatedone
	  objItemToInstall = updatesToInstall\GetObjectProperty("Item('" + Str(I) + "')")
    objItemInstall$ = objItemToInstall\GetStringProperty("Title()")
    InstallUninstallationNotes$ = objItemToInstall\GetStringProperty("UninstallationNotes()")
    objItemToInstall\GetObjectProperty("Identity()")
    InstalledUpdateID$ = objItemToInstall\GetStringProperty("UpdateID()")
    UpdateResult = installationResult\GetObjectProperty("GetUpdateResult(" + Str(I) + ")")
    OpResult = UpdateResult\GetIntegerProperty("ResultCode()")
    
    If OpResult = 2
      updatedone = updatedone + 1
      countinstalled = installcount - 1 ; subtract each one as its installed, when 0 all are installed
      WMIWrite_to_File_Updates(path_write_file$, "_______________________________________________________")
      WMIWrite_to_File_Updates(path_write_file$, "Installs remaining =   " + Str(countinstalled))
      WMIWrite_to_File_Updates(path_write_file$, "_______________________________________________________" + #CRLF$)
    EndIf
    
    Select OpResult
      Case 0
        UpdateOperation_Result$ = "Operation has not started."
      Case 1
        UpdateOperation_Result$ = "Operation is in progress."
      Case 2
        UpdateOperation_Result$ = "Operation completed successfully."
      Case 3
        UpdateOperation_Result$ = "Operation completed, but one or more errors occurred during the operation and the results are potentially incomplete."
      Case 4
        UpdateOperation_Result$ = "Operation failed to complete."
      Case 5
        UpdateOperation_Result$ = "Operation was aborted."
      Default
        UpdateOperation_Result$ = "Operation result could not be determined."
    EndSelect
    
    WMIWrite_to_File_Updates(path_write_file$, Str(I + 1) + "> " +  objItemInstall$ + "   " + UpdateOperation_Result$)
    WMIWrite_to_File_Updates(path_write_file$, Str(I + 1) + "Update ID   >  " + InstalledUpdateID$)
    objInstallKB = objItemToInstall\GetObjectProperty("KBArticleIDs()")
    For K = 0 To objInstallKB\GetIntegerProperty("Count") - 1
    objInstallKBStringItem$ = objInstallKB\GetStringProperty("Item(" + Str(K) + ")")
      WMIWrite_to_File_Updates(path_write_file$, "KB Article ID   >  " + objInstallKBStringItem$)
      If objKBStringItem$ <> ""
      WMIWrite_to_File_Updates(path_write_file$, "KB Article URL   >  " + "http://support.microsoft.com/kb/" + objInstallKBStringItem$)
      EndIf
      Delay(1)
    Next
    WMIWrite_to_File_Updates(path_write_file$, Str(I + 1) + "Uninstallation Notes   >  " + InstallUninstallationNotes$
    EndIf
    WMIWrite_to_File_Updates(path_write_file$, "----------------------------------------------------------------------------------------------")
  Delay(1)				
	Next

reboot = reboot
countinstalled = countinstalled
updatedone = updatedone
downloader\Release()
updatesToDownload\Release()
updatesToInstall\Release()
updateSession\Release()

;//////////reboot////////////
;uncomment below to use reboot if needed after install
If reboot => 1 And countinstalled = 0 And updatedone => 1
WMIWrite_to_File_Updates(path_write_file$, reboot_required$ + "   Rebooting computer in 30 seconds.")
Delay(30000)
WMIReboot() ; or WMIShutdownx() if we wish to just shutdown
EndIf

EndProcedure

If WMIIf_File_Existsx("C:\WUP_Info.txt") = 0
WMICreate_Text_File("C:\WUP_Info.txt")
Delay(1)
Else
WMIDelete_All_File("C:\WUP_Info.txt", #True)
Delay(1)
WMICreate_Text_File("C:\WUP_Info.txt")
Delay(1)
EndIf

WindowsUpdate_Download_InstallExx()
Post Reply