Windows Update Agent with PoSH – Part II

Let’s clean this script up a bit.  There were some uncessary line feeds, had a couple typos, needed some asthetic cleanup, and result codes were numerical, etc.  Let’s stick some comments in and change up the results display so that results are displayed using “spoken language” versus result codes.

The script has a group of 6 basic groups of tasks:

  • Show WUA version
  • List applicable updates (creates an initializes a WU session)
  • Download the applicable updates and list them one by one
  • Prep for installation (create the collection of updates to install)
  • Confirm installation.  Install if Yes.  Exit if No.  Exit with message if any other key pressed.
  • Error Handling

In essence, all this script does is reproduce the WU process as if you were going to the Windows Update website.  The only difference is that it downloads all applicable updates and prompts for confirmation for the installation.

#PowerShell script converted from VB Script here: http://msdn.microsoft.com/en-us/library/aa387102(VS.85).aspx
cls
# Show WUA version
$AgentInfo = new-object -comObject Microsoft.Update.AgentInfo
$WuaVersion = $AgentInfo.GetInfo("ProductVersionString")
Write-Host "Windows Update Manager Version: $WuaVersion"
Write-Host "`n"
# Create session and look for updates applicable to machine where script is run
$updateSession = new-object -comObject Microsoft.Update.Session
$updateSearcher = $updateSession.CreateupdateSearcher()
Write-Host "Searching for updates..."
$searchResult = $updateSearcher.Search("IsInstalled=0 and Type='Software'")
[System.Int32]$Results = $searchResult.Updates.Count
if ($Results -eq 0) {
	Write-Host "There are no applicable updates."
	return $Results
} else {
	Write-Host "List of applicable items on the machine: $Results"
	Write-Host "--------------------------------------------"
	for ([System.Int32]$i = 0; $i -lt $Results; $i ++ ) {
		$update = $searchResult.Updates.Item($i)
		Write-Host $update.title
	}
}
Write-Host "`n"
# List applicable updates
Write-Host "Creating collection of updates to download:"
$updatesToDownload = New-Object -comObject Microsoft.Update.UpdateColl
for ([System.Int32]$i = 0; $i -lt $Results; $i ++ ) {
	$update = $searchResult.Updates.Item($i)
	Write-Host "Adding - " $update.title
	$updatesToDownload.Add($update) | Out-Null
}
# Download the applicable updates and list them
Write-Host "Downloading updates..."
$downloader = $updateSession.CreateUpdateDownloader()
$downloader.Updates = $updatesToDownload
$downloader.Download() | Out-Null
Write-Host "`n"
Write-Host "List of downloaded updates:"
for ([System.Int32]$i = 0; $i -lt $Results; $i ++ ) {
	$update = $searchResult.Updates.Item($i)
	if ($update.IsDownloaded){
		Write-Host $update.title " - is downloaded."
	}
}
Write-Host "`n"
# Prep for installation
$updatesToInstall = New-Object -comObject Microsoft.Update.UpdateColl
Write-Host "Creating collection of downloaded updates to install:"
for ([System.Int32]$i = 0; $i -lt $Results; $i ++ ) {
	$update = $searchResult.Updates.Item($i)
	if ($update.IsDownloaded){
		Write-Host "Adding - " $update.title " - to install list."
		$updatesToInstall.Add($update) | Out-Null
	}
}
Write-Host "`n"
# Confirm installation. Install if Yes. Exit if No. Exit with message if any other key pressed.
$Response = $(Read-Host "Would you like to install updates now? (Y/N)")
if(($Response -eq "Yes") -or ($Response -eq "Y")){
	Write-Host "Installing updates...`n"
	$installer = $updateSession.CreateUpdateInstaller()
	$installer.Updates = $updatesToInstall
	$installationResult = $installer.Install()
	for ([System.Int32]$i = 0; $i -lt $updatesToInstall.count; $i ++ ) {
		$InstallationResults = $installationResult.GetUpdateResult($i).ResultCode
		Write-Host "Installation Result for: " $updatesToInstall.Item($i).Title " - Results:"
		switch ($InstallationResults) {
			0 {Write-Host Red "Installation of Update Not Started"}
			1 {Write-Host "Installation of Update in Progress" }
			2 {Write-Host -foregroundcolor Green "Installation of Update Succeeded"}
			3 {Write-Host -foregroundcolor Yellow "Installation of Update Succeeded with Errors"}
			4 {Write-Host -foregroundcolor Red "Installation of Update Failed"}
			5 {Write-Host -foregroundcolor Red "Installation of Update Aborted"}
		}
		Write-Host "Reboot Required? " $installationResult.RebootRequired "`n"
	}
	exit
} elseif (($Response -eq "No") -or ($Response -eq "N")) {
	exit
} else {
	Write-Host -foregroundcolor Red "`nPlease answer `"[Y]es`" or `"[N]o`" next time!`n"
	exit
}
Write-Host "`n"
# Error Handling
trap{
	Write-Host "ERROR: script execution was terminated.`n" $_.Exception.Message
	break
}

So, now we have results that make more sense.  Anything with an error is red.  Anything that succeeded with issues is yellow.  Succeess will be green and any other status is the default font color.

This is the K.I.S.S. approach.  We could create some functions and shorten this up.  I like a clean and simple approach.  It’s easy to read, there aren’t a bunch of abbreviations like I find in a lot of examples posted out on the internet of PoSH code.

There is an error in this script.  Did you see it?  Next we’ll look at where this is and at reboot options and other simple things we can do with WUA using PoSH.

Advertisements

A Simple VB to PowerShell Script Conversion (Windows Update Agent with PoSH)

During a discussion, the question arose about doing Windows Update from PowerShell (PoSH). A simple “I can’t see why not” was my response.

One of the powerful applications of PoSH, especially for the future, is the ability to more easily create deployment scripts for deploying new Windows NOS systems into the data center. As virtual computing becomes more mainstream, scripting the deployment makes a repeatable build a reality. It also ensures that the ability to rebuild a system quickly in the event of a disaster situation is also a reality.

My original objective was just to write some simple code and install 1 Windows Update.  I quickly found many examples but was left with way too many questions.

After just a minute or so of googl’ing, I ran across this MSDN post:

Searching, Downloading, and Installing Updates (Windows)

The script seemed simple enough.  So, my objective changed to converting this almost word-for-word from VB to PoSH.

Only a few slight changes have been made to the original script. The script’s important bits are pretty much the same as in VB, just converted to use PoSH.

#PowerShell script converted from VB Script here: http://msdn.microsoft.com/en-us/library/aa387102(VS.85).aspx
cls
$AgentInfo = new-object -comObject Microsoft.Update.AgentInfo
$WuaVersion = $AgentInfo.GetInfo("ProductVersionString")
Write-Host "Windows Update Manager Version: $WuaVersion"
Write-Host "`n"
$updateSession = new-object -comObject Microsoft.Update.Session
$updateSearcher = $updateSession.CreateupdateSearcher()
Write-Host "Searching for updates..."
$searchResult = $updateSearcher.Search("IsInstalled=0 and Type='Software'")
[System.Int32]$Results = $searchResult.Updates.Count
if ($Results -eq 0) {
	Write-Host "There are no applicable updates."
	return $Results
} else {
	Write-Host "List of applicable items on the machine: $Results"
	Write-Host "--------------------------------------------"
	for ([System.Int32]$i = 0; $i -lt $Results; $i ++ ) {
		$update = $searchResult.Updates.Item($i)
		Write-Host $update.title
	}
}
Write-Host "`n"
Write-Host "Creating collection of updates to download:"
$updatesToDownload = New-Object -comObject Microsoft.Update.UpdateColl
for ([System.Int32]$i = 0; $i -lt $Results; $i ++ ) {
	$update = $searchResult.Updates.Item($i)
	Write-Host "Adding - " $update.title
	$updatesToDownload.Add($update) | Out-Null
}
Write-Host "`n"
Write-Host "Downloading updates... `n"
$downloader = $updateSession.CreateUpdateDownloader()
$downloader.Updates = $updatesToDownload
$downloader.Download() | Out-Null
Write-Host "`n"
Write-Host "List of downloaded updates:"
for ([System.Int32]$i = 0; $i -lt $Results; $i ++ ) {
	$update = $searchResult.Updates.Item($i)
	if ($update.IsDownloaded){
		Write-Host $update.title " - is downloaded."
	}
}
Write-Host "`n"
$updatesToInstall = New-Object -comObject Microsoft.Update.UpdateColl
Write-Host "Creating collection of downloaded updates to install:"
for ([System.Int32]$i = 0; $i -lt $Results; $i ++ ) {
	$update = $searchResult.Updates.Item($i)
	if ($update.IsDownloaded){
		Write-Host "Adding - " $update.title " - to install list."
		$updatesToInstall.Add($update) | Out-Null
	}
}
Write-Host "`n"
$Response = $(Read-Host "Would you like to install updates now? (Y/N)")
if(($Response -eq "Yes") -or ($Response -eq "Y")){
	Write-Host "Installing updates...`n"
	$installer = $updateSession.CreateUpdateInstaller()
	$installer.Updates = $updatesToInstall
	$installationResult = $installer.Install()
	Write-Host -noNewLine "Installation results: " $installationResult.Resultcode
	Write-Host " Reboot Required? " $installationResult.RebootRequired
	Write-Host "`n"
	for ([System.Int32]$i = 0; $i -lt $updatesToInstall.count; $i ++ ) {
		Write-Host "Installation Result for: " $updatesToInstall.Item($i).Title "`t" $installationResult.GetUpdateResult($i).ResultCode
	}
	exit
} elseif (($Response -eq "No") -or ($Response -eq "N")) {
	exit
} else {
	Write-Host -foregroundcolor Red "`nPlease answer `"[Y]es`" or `"[N]o`" next time!`n"
	exit
}
Write-Host "`n"
Error Handling
trap{
	Write-Host "ERROR: script execution was terminated.`n" $_.Exception.Message
	break
}