Saturday, June 29, 2013

Final Hurdles While Installing Windows Updates

There are three different PC models here, all configured in the same way, all have to have Windows Updates installed on them automatically. However, while two of the models were happily updated, the third decided it does not like some of the updates and presented me with the screen similar to the following:

Turns out these two error codes are quite known problems.

The first one is solved, among some other options, by downloading and installing a specific update: , which is over 300MB in size. So in my case I had to do a check for the PC model by reading it via PowerShell

$strModel = (Get-WmiObject Win32_ComputerSystem).Model.Trim()

and if the model was the "weird" one, install this update.

The second one is solved by repairing the .NET Framework 4 installation. Fortunately, this can be done either silently or with unattended option. All in all, the fix for my two problems was applied as the following addition to the script and, fortunately, no additional restarts were required and after running this bit I could proceed to install updates as per my previous post.

if($strModel -Like "*WeirdModel*")
{
 Write-Host "Verifying .NET Framework 4 ..."
 Start-Process "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SetupCache\Client\setup.exe" "/repair /x86 /x64 /ia64 /parameterfolder Client /passive /norestart" -Wait
 Write-Host "Done."
 Write-Host "Installing System Update Readiness Tool ..."
 $readinessTool = Join-Path $win7Folder "Windows6.1-KB947821-v27-x64.msu"
 $toolCommand = $readinessTool + " /quiet /norestart"
 Write-Host $toolCommand
 Start-Process "wusa.exe" $toolCommand -Wait
 Write-Host "Done."
}

References:

Error Code 0x80073712 occurs in Windows Update or Microsoft Update
System Update Readiness Tool for Windows 7 (KB947821) [May 2013]
Error codes “0x80070643” or “0x643” occur when you install the .NET Framework updates
Silent install, repair and uninstall command lines for each version of the .NET Framework
by . Also posted on my website

Tuesday, June 25, 2013

Optimising Windows Updates Installation

It's a good thing that I wrote about Installing Windows Updates via Shell Script some time ago because today I needed to reuse that bit of a script and could not find it anywhere on my PC or our corporate network.

This time I'm reusing most of the functionality, but additionally do the following:

  • Make sure that the Windows Update service is started
  • Run a PowerShell script that passes a folder where the Windows update files are stored to the VbScript file
  • Execute VbScript to install all updates in a folder
  • Repeat. (I want to keep my "required" and "optional" updates separate

I was caught for a while trying to use PowerShell Set-Service and Start-Service commands and getting permission errors. I did not quite solve it, but found a simple workaround by utilising a command line:

@ECHO OFF

sc config wuauserv start= auto
net start wuauserv

Next, the PowerShell script is used to pass parameters to VbScript:

cscript .\Common\InstallUpdates.vbs $updatesFolder

Finally, the VbScript is almost the same as in the previous version, but note how the argument passed by PowerShell is parsed. The argument is the name of the folder where I placed the updates downloaded from Microsoft Update Catalog

Set args = WScript.Arguments
sfolder = args.Item(0)

Dim objfso, objShell
Dim iSuccess, iFail
Dim files, folderidx, Iretval, return
Dim fullFileName

Set objfso = CreateObject("Scripting.FileSystemObject")
Set folder = objfso.GetFolder(sfolder)
Set objShell = CreateObject("Wscript.Shell")

With (objfso)
 If .FileExists("C:\log.txt") Then
  Set logFile = objfso.OpenTextFile("C:\log.txt", 8, TRUE)
 Else
  Set logFile = objfso.CreateTextFile("C:\log.txt", TRUE)
 End If
End With

Set files = folder.Files
iSuccess = 0
iFail = 0

For each folderIdx In files

fullFileName = sfolder & "\" & folderidx.name

 If Ucase(Right(folderIdx.name,3)) = "MSU" then
  logFile.WriteLine("Installing " & folderidx.name & "...")
  iretval=objShell.Run ("wusa.exe " & fullFileName & " /quiet /norestart", 1, True)
  If (iRetVal = 0) or (iRetVal = 3010) then
   logFile.WriteLine("Success.")
   iSuccess = iSuccess + 1
  Else
   logFile.WriteLine("Failed.")
   iFail = iFail + 1
  End If
 ElseIf Ucase(Right(folderIdx.name,3)) = "EXE" Then
  logFile.WriteLine("Installing " & folderidx.name & "...")
  iretval = objShell.Run(fullFileName & " /q /norestart", 1, True)
  If (iRetVal = 0) or (iRetVal = 3010) then
   logFile.WriteLine("Success.")
   iSuccess = iSuccess + 1
  Else
   logFile.WriteLine("Failed.")
   iFail = iFail + 1
  End If
 End If
Next
 
wscript.echo iSuccess & " update(s) installed successfully and " & iFail & " update(s) failed. See C:\log.txt for details."

Disable the Windows Update service again if necessary

net stop wuauserv
sc config wuauserv start= disabled

References:

Managing Windows Services from the command line
Working with Command-Line Arguments
How do you pass a variable to VBS script in a powershell command?
Enable/Disable a Service via PowerShell
PowerShell queryService – Wait for a Dependency Starting Service
by . Also posted on my website