Install-WindowsUpdate.ps1

function Install-WindowsUpdate
{
    <#
    .Synopsis
        Installs windows updates
    .Description
        Installs windows updates discovered with Find-WindowsUpdate
    .Example
        Find-WindowsUpdate -Recommended |
            Install-WindowsUpdate
    .Link
        Find-WindowsUpdate
    #>

    [CmdletBinding(DefaultParameterSetName='UpdateName')]
    param(
    # The update object
    [Parameter(ValueFromPipeline=$true,
        Mandatory=$true,
        ParameterSetName='UpdateObject')]
    [ValidateScript({
        if ($_.pstypenames -notcontains 'System.__ComObject#{c1c2f21a-d2f4-4902-b5c6-8a081c19a890}') {
            throw "Not a windows update"
        }
        return $true
    })]
    $UpdateObject,
    
    # If set, will automatically reboot if an update requires it.
    [Switch]
    $Force
    )
 
    begin {
        $objCollection = New-Object -ComObject "Microsoft.Update.UpdateColl"
        $objServiceManager = New-Object -ComObject "Microsoft.Update.ServiceManager"
        $objSession = New-Object -ComObject "Microsoft.Update.Session"

    }   
    
    process {
        if ($psCmdlet.ParameterSetName -eq 'UpdateObject') {
            $UpdateObject.AcceptEula()
            $null = $objCollection.Add($UpdateObject)            
        }         
    }
    
    end {
        $objCollection2 = New-Object -ComObject "Microsoft.Update.UpdateColl"
        foreach($Update in $objCollection)
        {   
            $objCollectionTmp = New-Object -ComObject "Microsoft.Update.UpdateColl"
            $null = $objCollectionTmp.Add($Update) 
                
            $Downloader = $objSession.CreateUpdateDownloader() 
            $Downloader.Updates = $objCollectionTmp
            try {
                $DownloadResult = $Downloader.Download()
            } Catch {
                if($_ -match "HRESULT: 0x80240044") {
                    Write-Error "Must be an administrator"
                }
                return
            } 
            
            switch -exact ($DownloadResult.ResultCode)
            {
                0   { $Status = "NotStarted"}
                1   { $Status = "InProgress"}
                2   { $Status = "Downloaded"}
                3   { $Status = "DownloadedWithErrors"}
                4   { $Status = "Failed"}
                5   { $Status = "Aborted"}
            }
                    
            $log = New-Object psobject
                            
            if($Update.KBArticleIDs -ne "")    {$KB = "KB"+$Update.KBArticleIDs} else {$KB = ""}
            $size = [System.Math]::Round($Update.MaxDownloadSize/1MB,2)
                            
            $log | Add-Member -MemberType NoteProperty -Name Title -Value $Update.Title
            $log | Add-Member -MemberType NoteProperty -Name KB -Value $KB
            $log | Add-Member -MemberType NoteProperty -Name Size -Value $size
            $log | Add-Member -MemberType NoteProperty -Name Status -Value $Status
            
            $log | Select-Object  Title, KB, @{e={$_.Size};n='Size [MB]'}, Status 
                    
            if($DownloadResult.ResultCode -eq 2)
            {
                $objCollection2.Add($Update) | out-null
            }
            
            $objCollectionTmp = New-Object -ComObject "Microsoft.Update.UpdateColl"
            $null = $objCollectionTmp.Add($Update) 
                                    
            $objInstaller = $objSession.CreateUpdateInstaller()
            $objInstaller.Updates = $objCollectionTmp
                    
            try {                
                $InstallResult = $objInstaller.Install()
            } Catch {
                if($_ -match "HRESULT: 0x80240044") {
                    Write-Error "Must be an administrator"                    
                    return
                }
                 
            }       
            
            if(!$needsReboot)  { 
                $needsReboot = $installResult.RebootRequired 
            }  
            
            if ($needsReboot) { break } 
                         
            switch -exact ($InstallResult.ResultCode) {
               0   { $Status = "NotStarted"}
               1   { $Status = "InProgress"}
               2   { $Status = "Installed"}
               3   { $Status = "InstalledWithErrors"}
               4   { $Status = "Failed"}
               5   { $Status = "Aborted"}
            }
               
            $log = New-Object psobject 
                            
            if($Update.KBArticleIDs -ne "")    {$KB = "KB"+$Update.KBArticleIDs} else {$KB = ""}
            $size = [System.Math]::Round($Update.MaxDownloadSize/1MB,2)
                            
            $log | Add-Member -MemberType NoteProperty -Name Title -Value $Update.Title
            $log | Add-Member -MemberType NoteProperty -Name KB -Value $KB
            $log | Add-Member -MemberType NoteProperty -Name Size -Value $size
            $log | Add-Member -MemberType NoteProperty -Name Status -Value $Status
                
            $log | Select-Object  Title, KB, @{e={$_.Size};n='Size [MB]'}, Status 
        }
                
        if($needsReboot) {
            if($Force) {
                Restart-Computer -Force
            } else {
                Write-Error "Reboot required"
                return                
            }    
        }
    }
}