Update-WUModule.ps1

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
        }
    }

}