Quantcast
Channel: VMware Communities: Message List
Viewing all articles
Browse latest Browse all 230613

Automating patching of Windows Templates - strange error on 2012 R2..

$
0
0

So, last friday I was about to patch templates in different systems, and this time it needed some special care for Spectre/Meltdown patches and workarounds. Figured I may as well finally start scripting this procedure as it needed to be repeated on several templates. Most of this is done with Invoke-VMScript and the use of different powershell modules, and utilize some pre-standardisation of our templates (same DVD drive letter, same user/password, script in c:\install etc.).

 

In broad terms, the script (in it's current revision) does the following:

- Checks for powered on VMs in folders named "Templates" that has guestID matching "windows"

- Adds registry value so January security patches gets installed (No AV in base image, except Windows Defender)

- Adds NuGet package provider

- Installs PSwindowsupdate PS Module

- Downloads all windows updates (filtered if needed)

- Install all Windows Updates and reboots the machine

- Runs DISM with some parameters to ensure a small image

- Maps the ISO for VMware Tools and runs the installation silently, then dismounts the CD

- Shutting down the VM when complete

.. everything is logged to c:\temp\<name of VM>.txt

 

I have been trying to figure out why some VMs work, and some don't. Often the failure is due to problems with powershell, and I'm guessing that is because the machine is not logged on (or have some intrusive patch installed).

 

The errors I get are these:

Join-Path : Cannot bind argument to parameter 'Path' because it is null.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:47 char:77
+ ... osoft.PowerShell.Management\Join-Path -Path $env:LOCALAPPDATA -ChildP ...
+                                                 ~~~~~~~~~~~~~~~~~    + CategoryInfo          : InvalidData: (:) [Join-Path], ParameterBindingValidationException    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.JoinPathCommand

The variable '$script:PSGetAppLocalPath' cannot be retrieved because it has not been set.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:48 char:86
+ ... werShell.Management\Join-Path -Path $script:PSGetAppLocalPath -ChildP ...
+                                         ~~~~~~~~~~~~~~~~~~~~~~~~~    + CategoryInfo          : InvalidOperation: (script:PSGetAppLocalPath:String) [], RuntimeException    + FullyQualifiedErrorId : VariableIsUndefined

The variable '$script:PSGetAppLocalPath' cannot be retrieved because it has not been set.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:51 char:81
+ ... werShell.Management\Join-Path -Path $script:PSGetAppLocalPath -ChildP ...
+                                         ~~~~~~~~~~~~~~~~~~~~~~~~~    + CategoryInfo          : InvalidOperation: (script:PSGetAppLocalPath:String) [], RuntimeException    + FullyQualifiedErrorId : VariableIsUndefined

WARNING: The property 'Values' cannot be found on this object. Verify that the property exists.
WARNING: The property 'Keys' cannot be found on this object. Verify that the property exists.
WARNING: The variable '$script:PSGetModuleSourcesFilePath' cannot be retrieved because it has not been set.
PackageManagement\Install-Package : No match was found for the specified search criteria and module name 'PSWindowsUpdate'. Try Get-PSRepository to see all available registered module repositories.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:1772 char:21
+ ...          $null = PackageManagement\Install-Package @PSBoundParameters
+                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    + CategoryInfo          : ObjectNotFound: (Microsoft.Power....InstallPackage:InstallPackage) [Install-Package], Exception    + FullyQualifiedErrorId : NoMatchFoundForCriteria,Microsoft.PowerShell.PackageManagement.Cmdlets.InstallPackage

 

So far, it seems to be working if the console is logged on, or if the OS is 2008 R2.

Here's the script (it has no error handling or much intelligense yet, but it does the job..)

 

$guestuser = "administrator"
$guestpass = "password"
$skipupdates = "KB4033369,KB4033342"
$toolspath = "[Isofiles] VMware/VMware Tools/10.2.0/vmtools/windows.iso"

if( $Host -and $Host.UI -and $Host.UI.RawUI ) {
    $rawUI = $Host.UI.RawUI    $oldSize = $rawUI.BufferSize    $typeName = $oldSize.GetType( ).FullName    $newSize = New-Object $typeName (120, $oldSize.Height)    $rawUI.BufferSize = $newSize  }

Clear-Host

foreach ($vm in (Get-Folder Templates | Get-VM | Sort-Object Name | Where-Object {$_.PowerState -eq "PoweredOn" -and $_.guestid -match "windows" })) {
    Write-Host Processing: $vm.name    $file = "c:\temp\$($vm.name).txt"    $now = get-date    add-content $file "Actions started on $now"    Write-host " - Adding registry values for Spectre/Meltdown patches"    add-content $file "Adding registry values for Spectre/Meltdown patches"    $output = Invoke-VMScript -vm $vm -ScriptText "reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\QualityCompat /v cadca5fe-87d3-4b96-b7fb-a231484277cc /t REG_DWORD /d 0 /f" -GuestUser $guestuser -GuestPassword $guestpass -ScriptType bat    add-content $file $output    Write-host " - Installing NuGet package provider"    add-content $file "Installing NuGet package provider"    $output = Invoke-VMScript -vm $vm -ScriptText "Install-PackageProvider nuget -force" -GuestUser $guestuser -GuestPassword $guestpass -ScriptType PowerShell    add-content $file $output    Write-host " - Installing PSWindowsUpdate module"    add-content $file "Installing PSWindowsUpdate module"    $output = Invoke-VMScript -vm $vm -ScriptText "Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; Import-Module PowerShellGet; Start-Sleep -Seconds 10; Install-Module -Name PSWindowsUpdate -force -scope AllUsers" -GuestUser $guestuser -GuestPassword $guestpass -ScriptType PowerShell    add-content $file $output    if ($skipupdates -eq "") {        Write-host " - Downloading all Windows Updates"        add-content $file "Downloading all Windows Updates"        $output = Invoke-VMScript -vm $vm -ScriptText "Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; Import-Module PSWindowsUpdate; Start-Sleep -seconds 10; Get-WindowsUpdate -Download -Verbose -AcceptAll" -GuestUser $guestuser -GuestPassword $guestpass -ScriptType PowerShell        add-content $file $output        Write-host " - Installing all Windows Updates"        add-content $file "Installing all Windows Updates"        $output = Invoke-VMScript -vm $vm -ScriptText "Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; Import-Module PSWindowsUpdate; Start-Sleep -seconds 10; Get-WindowsUpdate -MicrosoftUpdate -AcceptAll -Install -AutoReboot -Verbose" -GuestUser $guestuser -GuestPassword $guestpass -ScriptType PowerShell        add-content $file $output    } else {        Write-host " - Downloading all Windows Updates, except $skipupdates"        add-content $file "Downloading all Windows Updates, except $skipupdates"        $output = Invoke-VMScript -vm $vm -ScriptText "Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; Import-Module PSWindowsUpdate; Start-Sleep -seconds 10; Get-WindowsUpdate -Download -Verbose -AcceptAll -NotKBArticleID $skipupdates" -GuestUser $guestuser -GuestPassword $guestpass -ScriptType PowerShell        add-content $file $output        Write-host " - Installing all Windows Updates, except $skipupdates"        add-content $file "Installing all Windows Updates, except $skipupdates"        $output = Invoke-VMScript -vm $vm -ScriptText "Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; Import-Module PSWindowsUpdate; Start-Sleep -seconds 10; Get-WindowsUpdate -MicrosoftUpdate -AcceptAll -Install -AutoReboot -NotKBArticleID $skipupdates -Verbose" -GuestUser $guestuser -GuestPassword $guestpass -ScriptType PowerShell        add-content $file $output    }    Write-Host " - Waiting 180 seconds for reboot to complete"    Start-Sleep -Seconds 180    Write-host " - Running cleanup script"    add-content $file "Running cleanup script"    $output = Invoke-VMScript -ToolsWaitSecs 360 -vm $vm -ScriptText "c:\install\cleanup.cmd" -GuestUser $guestuser -GuestPassword $guestpass -ScriptType bat    add-content $file $output    Write-Host " - Upgrading VMware Tools"    add-content $file "Upgrading VMware Tools"    Get-CDDrive -vm $vm | Set-CDDrive -IsoPath $toolspath -Connected:$true -Confirm:$false | Out-Null    Write-Host "  - Waiting for ISO to be mounted"    Start-Sleep -Seconds 15    $output = Invoke-VMScript -ToolsWaitSecs 360 -vm $vm -ScriptText "Z:\setup64.exe /s /v ""/qn REBOOT=Force ADDLOCAL=ALL REMOVE=Hgfs""" -GuestUser $guestuser -GuestPassword $guestpass -ScriptType bat    add-content $file $output    #sleep added due to vmware tools upgrade trashing the connection    Write-Host "  - Waiting five minutes for VMware Tools installation to complete"    Start-Sleep -Seconds 300    Write-Host "  - Dismounting ISO file"    Get-CDDrive -vm $vm | Set-CDDrive -NoMedia -Connected:$false -Confirm:$false | Out-Null    Write-host " - Shutting down the VM"    add-content $file "Shutting down the VM"    $output = Invoke-VMScript -vm $vm -ScriptText "shutdown /s /f /t 10 /d p:0:0" -GuestUser $guestuser -GuestPassword $guestpass -ScriptType Bat    add-content $file $output
}

 

Have anyone else encountered problems with Invoke-VMScript and powershell?

(Note, I could prepare a BAT/CMD that does all the above, but this can be used for other purposes as well when automating customer patching later on)

 

Message was edited by: Andreas Cederlund Forgot to edit out password :-)


Viewing all articles
Browse latest Browse all 230613

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>