Function Update-WUModule
{
<#
.SYNOPSIS
Invoke Get-WUInstall remotely.
.DESCRIPTION
Use Invoke-WUInstall to invoke Windows Update install remotly. It Based on TaskScheduler because
CreateUpdateDownloader() and CreateUpdateInstaller() methods can't be called from a remote computer - E_ACCESSDENIED.
Note:
Because we do not have the ability to interact, is recommended use -AcceptAll with WUInstall filters in script block.
.PARAMETER ComputerName
Specify computer name.
.PARAMETER PSWUModulePath
Destination of PSWindowsUpdate module. Default is C:\Windows\system32\WindowsPowerShell\v1.0\Modules\PSWindowsUpdate
.PARAMETER OnlinePSWUSource
Link to online source on TechNet Gallery.
.PARAMETER LocalPSWUSource
Path to local source on your machine. If you cant use [System.IO.Compression.ZipFile] you must manualy unzip source and set path to it.
.PARAMETER CheckOnly
Only check current version of PSWindowsUpdate module. Don't update it.
.EXAMPLE
PS C:\> Update-WUModule
.EXAMPLE
PS C:\> Update-WUModule -LocalPSWUSource "C:\Windows\system32\WindowsPowerShell\v1.0\Modules\PSWindowsUpdate" -ComputerName PC2,PC3,PC4
.NOTES
Author: Michal Gajda
Blog : http://commandlinegeeks.com/
.LINK
Get-WUInstall
#>
[CmdletBinding(
SupportsShouldProcess=$True,
ConfirmImpact="High"
)]
param
(
[Parameter(ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True)]
[String[]]$ComputerName = "localhost",
[String]$PSWUModulePath = "C:\Windows\system32\WindowsPowerShell\v1.0\Modules\PSWindowsUpdate",
[String]$OnlinePSWUSource = "http://gallery.technet.microsoft.com/2d191bcd-3308-4edd-9de2-88dff796b0bc",
[String]$SourceFileName = "PSWindowsUpdate.zip",
[String]$LocalPSWUSource,
[Switch]$CheckOnly,
[Switch]$Debuger
)
Begin
{
If($PSBoundParameters['Debuger'])
{
$DebugPreference = "Continue"
} #End If $PSBoundParameters['Debuger']
$User = [Security.Principal.WindowsIdentity]::GetCurrent()
$Role = (New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
if(!$Role)
{
Write-Warning "To perform some operations you must run an elevated Windows PowerShell console."
} #End If !$Role
if($LocalPSWUSource -eq "")
{
Write-Debug "Prepare temp location"
$TEMPDentination = [environment]::GetEnvironmentVariable("Temp")
#$SourceFileName = $OnlinePSWUSource.Substring($OnlinePSWUSource.LastIndexOf("/")+1)
$ZipedSource = Join-Path -Path $TEMPDentination -ChildPath $SourceFileName
$TEMPSource = Join-Path -Path $TEMPDentination -ChildPath "PSWindowsUpdate"
Try
{
$WebClient = New-Object System.Net.WebClient
$WebSite = $WebClient.DownloadString($OnlinePSWUSource)
$WebSite -match "/file/41459/\d*/PSWindowsUpdate.zip" | Out-Null
$OnlinePSWUSourceFile = $OnlinePSWUSource + $matches[0]
Write-Debug "Download latest PSWindowsUpdate module from website: $OnlinePSWUSourceFile"
#Start-BitsTransfer -Source $OnlinePSWUSource -Destination $TEMPDentination
$WebClient.DownloadFile($OnlinePSWUSourceFile,$ZipedSource)
} #End Try
catch
{
Write-Error "Can't download the latest PSWindowsUpdate module from website: $OnlinePSWUSourceFile" -ErrorAction Stop
} #End Catch
Try
{
if(Test-Path $TEMPSource)
{
Write-Debug "Cleanup old PSWindowsUpdate source"
Remove-Item -Path $TEMPSource -Force -Recurse
} #End If Test-Path $TEMPSource
Write-Debug "Unzip the latest PSWindowsUpdate module"
[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null
[System.IO.Compression.ZipFile]::ExtractToDirectory($ZipedSource,$TEMPDentination)
$LocalPSWUSource = Join-Path -Path $TEMPDentination -ChildPath "PSWindowsUpdate"
} #End Try
catch
{
Write-Error "Can't unzip the latest PSWindowsUpdate module" -ErrorAction Stop
} #End Catch
Write-Debug "Unblock the latest PSWindowsUpdate module"
Get-ChildItem -Path $LocalPSWUSource | Unblock-File
} #End If $LocalPSWUSource -eq ""
$ManifestPath = Join-Path -Path $LocalPSWUSource -ChildPath "PSWindowsUpdate.psd1"
$TheLatestVersion = (Test-ModuleManifest -Path $ManifestPath).Version
Write-Verbose "The latest version of PSWindowsUpdate module is $TheLatestVersion"
}
Process
{
ForEach($Computer in $ComputerName)
{
if($Computer -eq [environment]::GetEnvironmentVariable("COMPUTERNAME") -or $Computer -eq ".")
{
$Computer = "localhost"
} #End If $Computer -eq [environment]::GetEnvironmentVariable("COMPUTERNAME") -or $Computer -eq "."
if($Computer -eq "localhost")
{
$ModuleTest = Get-Module -ListAvailable -Name PSWindowsUpdate
} #End if $Computer -eq "localhost"
else
{
if(Test-Connection $Computer -Quiet)
{
Write-Debug "Check if PSWindowsUpdate module exist on $Computer"
Try
{
$ModuleTest = Invoke-Command -ComputerName $Computer -ScriptBlock {Get-Module -ListAvailable -Name PSWindowsUpdate} -ErrorAction Stop
} #End Try
Catch
{
Write-Warning "Can't access to machine $Computer. Try use: winrm qc"
Continue
} #End Catch
} #End If Test-Connection $Computer -Quiet
else
{
Write-Warning "Machine $Computer is not responding."
} #End Else Test-Connection -ComputerName $Computer -Quiet
} #End Else $Computer -eq "localhost"
If ($pscmdlet.ShouldProcess($Computer,"Update PSWindowsUpdate module from $($ModuleTest.Version) to $TheLatestVersion"))
{
if($Computer -eq "localhost")
{
if($ModuleTest.Version -lt $TheLatestVersion)
{
if($CheckOnly)
{
Write-Verbose "Current version of PSWindowsUpdate module is $($ModuleTest.Version)"
} #End If $CheckOnly
else
{
Write-Verbose "Copy source files to PSWindowsUpdate module path"
Get-ChildItem -Path $LocalPSWUSource | Copy-Item -Destination $ModuleTest.ModuleBase -Force
$AfterUpdateVersion = [String]((Get-Module -ListAvailable -Name PSWindowsUpdate).Version)
Write-Verbose "$($Computer): Update completed: $AfterUpdateVersion"
}#End Else $CheckOnly
} #End If $ModuleTest.Version -lt $TheLatestVersion
else
{
Write-Verbose "The newest version of PSWindowsUpdate module exist"
} #ed Else $ModuleTest.Version -lt $TheLatestVersion
} #End If $Computer -eq "localhost"
else
{
Write-Debug "Connection to $Computer"
if($ModuleTest -eq $null)
{
$PSWUModulePath = $PSWUModulePath -replace ":","$"
$DestinationPath = "\\$Computer\$PSWUModulePath"
if($CheckOnly)
{
Write-Verbose "PSWindowsUpdate module on machine $Computer doesn't exist"
} #End If $CheckOnly
else
{
Write-Verbose "PSWindowsUpdate module on machine $Computer doesn't exist. Installing: $DestinationPath"
Try
{
New-Item -ItemType Directory -Path $DestinationPath -Force | Out-Null
Get-ChildItem -Path $LocalPSWUSource | Copy-Item -Destination $DestinationPath -Force
$AfterUpdateVersion = [string](Invoke-Command -ComputerName $Computer -ScriptBlock {(Get-Module -ListAvailable -Name PSWindowsUpdate).Version} -ErrorAction Stop)
Write-Verbose "$($Computer): Update completed: $AfterUpdateVersion"
} #End Try
Catch
{
Write-Warning "Can't install PSWindowsUpdate module on machine $Computer."
} #End Catch
} #End Else $CheckOnly
} #End If $ModuleTest -eq $null
elseif($ModuleTest.Version -lt $TheLatestVersion)
{
$PSWUModulePath = $ModuleTest.ModuleBase -replace ":","$"
$DestinationPath = "\\$Computer\$PSWUModulePath"
if($CheckOnly)
{
Write-Verbose "Current version of PSWindowsUpdate module on machine $Computer is $($ModuleTest.Version)"
} #End If $CheckOnly
else
{
Write-Verbose "PSWindowsUpdate module version on machine $Computer is ($($ModuleTest.Version)) and it's older then downloaded ($TheLatestVersion). Updating..."
Try
{
Get-ChildItem -Path $LocalPSWUSource | Copy-Item -Destination $DestinationPath -Force
$AfterUpdateVersion = [string](Invoke-Command -ComputerName $Computer -ScriptBlock {(Get-Module -ListAvailable -Name PSWindowsUpdate).Version} -ErrorAction Stop)
Write-Verbose "$($Computer): Update completed: $AfterUpdateVersion"
} #End Try
Catch
{
Write-Warning "Can't updated PSWindowsUpdate module on machine $Computer"
} #End Catch
} #End Else $CheckOnly
} #End ElseIf $ModuleTest.Version -lt $TheLatestVersion
else
{
Write-Verbose "Current version of PSWindowsUpdate module on machine $Computer is $($ModuleTest.Version)"
} #End Else $ModuleTest.Version -lt $TheLatestVersion
} #End Else $Computer -eq "localhost"
} #End If $pscmdlet.ShouldProcess($Computer,"Update PSWindowsUpdate module")
} #End ForEach $Computer in $ComputerName
}
End
{
if($LocalPSWUSource -eq "")
{
Write-Debug "Cleanup PSWindowsUpdate source"
if(Test-Path $ZipedSource -ErrorAction SilentlyContinue)
{
Remove-Item -Path $ZipedSource -Force
} #End If Test-Path $ZipedSource
if(Test-Path $TEMPSource -ErrorAction SilentlyContinue)
{
Remove-Item -Path $TEMPSource -Force -Recurse
} #End If Test-Path $TEMPSource
}
}
}