Posted On August 7, 2020

PowerShell: Update Local Windows Machine

kimconnect 0 comments
blog.KimConnect.com >> Codes >> PowerShell: Update Local Windows Machine

This script is meant to be ran on a local computer. To update remote machines, use this script here.

# updateLocalWindows_v0.0.5.ps1
# This function will quickly patch the local Windows machine
# There are two options:
#- Windows Update: will only patch the Windows Operating System
#- Microsoft Update (default): will patch all Microsoft products detected on the system
#- This version will ONLY work when running as Session 0 or console. It's NOT intended to be invoked as a WinRM session.
#
# Usage:
# 1. updatelocalWindows
# 2. updateLocalWindows -verbose $false
# 3. updateLocalWindows -microsoftUpdate $false
# 4. updateLocalWindows -microsoftUpdate $false -verbose $false
# 5. updateLocalWindows -microsoftUpdate $true -notCategory 'Drivers'

function updateLocalWindows($microsoftUpdates=$true,$verbose=$false,$notCategory='Drivers'){
  if($verbose){$localTimer=[System.Diagnostics.Stopwatch]::StartNew()}
  $tempDir='C:\temp\'
  if(Test-Path $tempDir){$null=mkdir $tempDir -force}
  if(!(test-WsMan $env:computername)){winrm quickconfig}
  function checkPendingReboot{
          function checkRegistryPendingReboot{
                  if (Get-ChildItem 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending' -EA Ignore) { return $true }
                  if (Get-Item 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired' -EA Ignore) { return $true }
                  if (Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Name PendingFileRenameOperations -EA Ignore) { return $true }
                  try { 
                  $util = [wmiclass]'\\.\root\ccm\clientsdk:CCM_ClientUtilities'
                  $status = $util.DetermineIfRebootPending()
                  if(($status -ne $null) -and $status.RebootPending){
                      return $true
                  }
                  }catch{}
                  return $false          
          }
          return checkRegistryPendingReboot
      }
 
  function updateWindows($microsoftUpdates,$notCategory){
      #Install the PowerShell Windows Update module
      $checkModule=Get-Module -ListAvailable -Name PSWindowsUpdate
      if(!($checkModule)){
          [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
          $nugetInstalled=Get-PackageProvider nuget -EA Ignore
          if(!$nugetInstalled){Install-PackageProvider -Name Nuget -RequiredVersion 2.8.5.201 -Force}          
          $trustPSGallery=(Get-psrepository -Name 'PSGallery').InstallationPolicy
          If($trustPSGallery -ne 'Trusted'){
              Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
              }        
          Install-Module PSWindowsUpdate -Confirm:$false
          }
  
      # Perform Updates
      set-executionpolicy bypass -force
      if($bypassWsus){
          }
      # -MicrosoftUpdate: include other Microsoft products (Office, Silverlight, Visual C++, etc.)
      # -WindowsUpdate: include only Windows updates
      if($microsoftUpdates){
          # Register Microsoft Update Service if it has not been registered
          $microsoftUpdateId='7971f918-a847-4430-9279-4a52d1efe18d'
          if (!($microsoftUpdateId -in (Get-WUServiceManager).ServiceID)){
              Add-WUServiceManager -ServiceID $microsoftUpdateId -Confirm:$false
              }
          $updateCommand='Get-WindowsUpdate -AcceptAll -MicrosoftUpdate -Install -IgnoreReboot'+$(if($notCategory){' -NotCategory '+$notCategory})
      }else{
          $updateCommand='Get-WindowsUpdate -AcceptAll -WindowsUpdate -Install -IgnoreReboot'+$(if($notCategory){' -NotCategory '+$notCategory})
      }
      Invoke-Expression $updateCommand            
      $pendingReboot=checkPendingReboot $computer
      if(!$pendingReboot){
          write-host 'No pending reboots detected.' -ForegroundColor Green
      }else{
          write-host 'Pending reboots detected.' -ForegroundColor Yellow
          }        
      }

  function checkUpdates($microsoftUpdates,$notCategory='drivers',$verbose=$false){
      ## This runs into the constraints of unelevated process being prevented from reading stdout of an elevated session
      ## Source: https:// docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process?view=netcore-3.1 
      #$startInfo = New-Object System.Diagnostics.ProcessStartInfo
      #$startInfo.FileName = $exe
      #$startInfo.RedirectStandardError = $true
      #$startInfo.RedirectStandardOutput = $true    
      #$startInfo.Arguments = "(Get-wulist -verbose).kb.count"
      #$startInfo.CreateNoWindow = $false
      #$startInfo.UseShellExecute = $false
      ##$startInfo.Verb = "runas"
      ##$startInfo.UseShellExecute = $true
      ##Error when trying to run as Administrator: Exception calling 'Start' with "0" argument(s):
      ## 'The Process object must have the UseShellExecute property set to false in order to redirect IO streams.'
      #$process = New-Object System.Diagnostics.Process
      #$process.StartInfo = $startInfo
      #$process.Start()
      #$process.WaitForExit()
      #$stdout = $process.StandardOutput.ReadToEnd()
      #$stderr = $process.StandardError.ReadToEnd()
      #Write-Host 'stdout: '+ $stdout
      #if($stderr){Write-Host 'stderr: '+$stderr -ForegroundColor Red}
      #Write-Host 'exit code: '+$($process.ExitCode)
      #return $stdout

      # This is the workaround
      $tempFile='C:\temp\availableUpdatesCount.txt'
      $checkUpdates=@"
          `$x=(Get-wulist -verbose $(if($microsoftUpdates){'-MicrosoftUpdate '}) $(if($notCategory){'-NotCategory '+$notCategory})).kb.count
          write-host `$x
          New-Item '$tempFile' -ItemType File -Value `$x -Force
"@
      Start-Process -verb Runas powershell.exe $checkUpdates -Wait -WindowStyle $(if($verbose){'normal'}else{'minimized'})
      $result=Get-Content $tempFile
      Start-Process -verb Runas powershell.exe "remove-item '$tempFile' -Force" -WindowStyle hidden -Wait 
      return $result
  }

  $Host.UI.RawUI.BackgroundColor = 'Black'
  $myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
  $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
  $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
  if ($myWindowsPrincipal.IsInRole($adminRole)){
      write-host "This session is running under the context of the system 'Administrator'" -ForegroundColor Green
  }else{
      write-warning "This session is NOT in the context of 'Administrator'"
      }

    updateWindows $microsoftUpdates $notCategory
    [bool]$isPendingReboot=checkPendingReboot
    [int]$updatesAvailable=checkUpdates $microsoftUpdates $notCategory $verbose
    if(!$isPendingReboot -and !$updatesAvailable){
        write-host "`r`nWindows updates completed" -ForegroundColor Green        
        $completed=$true
    }else{
        if($isPendingReboot){write-host "`r`nPending reboots detected." -ForegroundColor Yellow}
        if($updatesAvailable){write-host "`r`nMissing $updatesAvailable updates." -ForegroundColor Yellow}
        $completed=$false
        }   
  if($verbose){
      $minutes=[math]::round($localTimer.Elapsed.TotalMinutes,2)
      write-host "$minutes minutes elapsed"
  }
  return $completed
}

updateLocalWindows
# updateLocalWindows_v0.0.4.ps1
# This function will quickly patch the local Windows machine
# There are two options:
#- Windows Update: will only patch the Windows Operating System
#- Microsoft Update (default): will patch all Microsoft products detected on the system
#- This version will ONLY works when running as Session 0 or console. It's NOT intended to be invoked as a WinRM session.
#
# Usage:
# 1. updatelocalWindows
# 2. updateLocalWindows -verbose $false
# 3. updateLocalWindows -microsoftUpdate $false
# 4. updateLocalWindows -microsoftUpdate $false -verbose $false
# 5. updateLocalWindows -microsoftUpdate $true -notCategory 'Drivers'

function updateLocalWindows($microsoftUpdates=$true,$verbose=$false,$notCategory='Drivers'){
  if($verbose){$localTimer=[System.Diagnostics.Stopwatch]::StartNew()}
  $tempDir='C:\temp\'
  if(Test-Path $tempDir){$null=mkdir $tempDir -force}

if(!(test-WsMan $env:computername)){winrm quickconfig}

  function checkPendingReboot{
          function checkRegistryPendingReboot{
                  if (Get-ChildItem 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending' -EA Ignore) { return $true }
                  if (Get-Item 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired' -EA Ignore) { return $true }
                  if (Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Name PendingFileRenameOperations -EA Ignore) { return $true }
                  try { 
                  $util = [wmiclass]'\\.\root\ccm\clientsdk:CCM_ClientUtilities'
                  $status = $util.DetermineIfRebootPending()
                  if(($status -ne $null) -and $status.RebootPending){
                      return $true
                  }
                  }catch{}
                  return $false          
          }
          return checkRegistryPendingReboot
      }
 
  function updateWindows($microsoftUpdates,$notCategory){
      #Install the PowerShell Windows Update module
      $checkModule=Get-Module -ListAvailable -Name PSWindowsUpdate
      if(!($checkModule)){
          [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
          $nugetInstalled=Get-PackageProvider nuget
          if(!$nugetInstalled){Install-PackageProvider -Name Nuget -RequiredVersion 2.8.5.201 -Force -confirm:$false}          
          $trustPSGallery=(Get-psrepository -Name 'PSGallery').InstallationPolicy
          If($trustPSGallery -ne 'Trusted'){
              Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
              }        
          Install-Module PSWindowsUpdate -Confirm:$false
          }
  
      # Perform Updates
      set-executionpolicy bypass -force
      if($bypassWsus){
          }
      # -MicrosoftUpdate: include other Microsoft products (Office, Silverlight, Visual C++, etc.)
      # -WindowsUpdate: include only Windows updates
      if($microsoftUpdates){
          # Register Microsoft Update Service if it has not been registered
          $microsoftUpdateId='7971f918-a847-4430-9279-4a52d1efe18d'
          if (!($microsoftUpdateId -in (Get-WUServiceManager).ServiceID)){
              Add-WUServiceManager -ServiceID $microsoftUpdateId -Confirm:$false
              }
          $updateCommand='Get-WindowsUpdate -AcceptAll -MicrosoftUpdate -Install -IgnoreReboot'+$(if($notCategory){' -NotCategory '+$notCategory})
      }else{
          $updateCommand='Get-WindowsUpdate -AcceptAll -WindowsUpdate -Install -IgnoreReboot'+$(if($notCategory){' -NotCategory '+$notCategory})
      }
      Invoke-Expression $updateCommand
            
      $pendingReboot=checkPendingReboot $computer
      if(!$pendingReboot){
          write-host 'Updates are completed.' -ForegroundColor Green
          return $true
      }else{
          write-host 'Please reboot and trigger updates again to complete the process.' -ForegroundColor Yellow
          return $false
          }        
      }

  function checkUpdates($microsoftUpdates,$notCategory='drivers',$verbose=$false){
      ## This runs into the constraints of unelevated process being prevented from reading stdout of an elevated session
      ## Source: https:// docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process?view=netcore-3.1 
      #$startInfo = New-Object System.Diagnostics.ProcessStartInfo
      #$startInfo.FileName = $exe
      #$startInfo.RedirectStandardError = $true
      #$startInfo.RedirectStandardOutput = $true    
      #$startInfo.Arguments = "(Get-wulist -verbose).kb.count"
      #$startInfo.CreateNoWindow = $false
      #$startInfo.UseShellExecute = $false
      ##$startInfo.Verb = "runas"
      ##$startInfo.UseShellExecute = $true
      ##Error when trying to run as Administrator: Exception calling 'Start' with "0" argument(s):
      ## 'The Process object must have the UseShellExecute property set to false in order to redirect IO streams.'
      #$process = New-Object System.Diagnostics.Process
      #$process.StartInfo = $startInfo
      #$process.Start()
      #$process.WaitForExit()
      #$stdout = $process.StandardOutput.ReadToEnd()
      #$stderr = $process.StandardError.ReadToEnd()
      #Write-Host 'stdout: '+ $stdout
      #if($stderr){Write-Host 'stderr: '+$stderr -ForegroundColor Red}
      #Write-Host 'exit code: '+$($process.ExitCode)
      #return $stdout

      # This is the workaround
      $tempFile='C:\temp\availableUpdatesCount.txt'
      $checkUpdates=@"
          `$x=(Get-wulist -verbose $(if($microsoftUpdates){'-MicrosoftUpdate '}) $(if($notCategory){'-NotCategory '+$notCategory})).kb.count
          write-host `$x
          New-Item '$tempFile' -ItemType File -Value `$x -Force
"@
      Start-Process -verb Runas powershell.exe $checkUpdates -Wait -WindowStyle $(if($verbose){'normal'}else{'minimized'})
      $result=Get-Content $tempFile
      Start-Process -verb Runas powershell.exe "remove-item '$tempFile' -Force" -WindowStyle hidden -Wait 
      return $result
  }

  $functionScript = @"
      `$Host.UI.RawUI.BackgroundColor = 'Black'
      `$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
      `$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal(`$myWindowsID)
      `$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
      if (`$myWindowsPrincipal.IsInRole(`$adminRole)){
          write-host "This session is running under the context of the system 'Administrator'" -ForegroundColor Green
      }else{
          write-warning "This session is NOT in the context of 'Administrator'"
          }
      Function checkPendingReboot{
          $(Get-Command checkPendingReboot|Select -expand Definition)
      }
      Function updateWindows{
          $(Get-Command updateWindows|Select -expand Definition)
      }
      updateWindows $microsoftUpdates $notCategory
"@
   
  write-host "Spawning a background process to update Windows as Administrator..."
  do{
      $process=Start-Process -verb Runas powershell $functionScript -WindowStyle $(if($verbose){'normal'}else{'minimized'}) -PassThru
      $lineBreak=60
      $dotCount=0
      $minute=0
      write-host "Minute`r`n$minute`t:" -NoNewline -ForegroundColor Yellow
      do {
          if($dotCount++ -lt $lineBreak){
              write-host '.' -NoNewline
          }else{
              $minute++
              write-host "`r`n$minute`t:" -ForegroundColor Yellow -NoNewline
              $dotCount=0
              }
          Start-Sleep -s 1
      }until (!$process.Responding)

      [bool]$isPendingReboot=checkPendingReboot
      [int]$updatesAvailable=checkUpdates $microsoftUpdates $notCategory $verbose
      if(!$isPendingReboot -and !$updatesAvailable){
          write-host "`r`nWindows updates completed" -ForegroundColor Green        
          $completed=$true
      }else{
          if($isPendingReboot){write-host "`r`nPending reboots detected." -ForegroundColor Yellow}
          if($updatesAvailable){write-host "`r`nMissing $updatesAvailable updates." -ForegroundColor Yellow}
          $completed=$false
          }
  }until(!$updatesAvailable -or $isPendingReboot)
   
  if($verbose){
      $minutes=[math]::round($localTimer.Elapsed.TotalMinutes,2)
      write-host "$minutes minutes elapsed"
  }
  return $completed
}

updateLocalWindows
# updateLocalWindows_v0.0.5.ps1
# Note: broken

function updateLocalWindows{
    param(
        $microsoftUpdates=$false, # Setting this to True also means WSUS shall be bypassed    
        $notCategory='Drivers',
        $verbose=$false
    )
    if($verbose){$localTimer=[System.Diagnostics.Stopwatch]::StartNew()}
 
    function checkPendingReboot{ 
        function checkRegistry{
            if (Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending" -EA Ignore) { return $true }
            if (Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootInProgress" -EA Ignore) { return $true }
            if (Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" -EA Ignore) { return $true }
            if (Get-Item "HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\PackagesPending" -EA Ignore) { return $true }
            if (Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\PostRebootReporting" -EA Ignore) { return $true }
            if (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name PendingFileRenameOperations -EA Ignore) { return $true }
            if (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name PendingFileRenameOperations2 -EA Ignore) { return $true }
            try{ 
                $util = [wmiclass]"\\.\root\ccm\clientsdk:CCM_ClientUtilities"
                $status = $util.DetermineIfRebootPending()
                if(($null -ne $status) -and $status.RebootPending){
                    $result.SCCMRebootPending = $true
                }
            }catch{
                return $false
            }                    
        }
        return checkRegistry
    }    

    function updateWindows($microsoftUpdates,$notCategory){
        #Install the PowerShell Windows Update module
        $checkModule=Get-Module -ListAvailable -Name PSWindowsUpdate
        if(!($checkModule)){
            [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
            # Set PowerShell Gallery as Trusted to bypass prompts
            #$trustPSGallery=(Get-psrepository -Name 'PSGallery').InstallationPolicy
            If($trustPSGallery -ne 'Trusted'){
                Install-PackageProvider -Name Nuget -Force
                #Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
                }        
            Install-Module PSWindowsUpdate -Confirm:$false
            }
   
        # Perform Updates
        set-executionpolicy bypass -force
        # -MicrosoftUpdate: include other Microsoft products (Office, Silverlight, Visual C++, etc.)
        # -WindowsUpdate: include only Windows updates
        if($microsoftUpdates){
            # Register Microsoft Update Service if it has not been registered
            $microsoftUpdateId='7971f918-a847-4430-9279-4a52d1efe18d'
            if (!($microsoftUpdateId -in (Get-WUServiceManager).ServiceID)){
                Add-WUServiceManager -ServiceID $microsoftUpdateId -Confirm:$false
                }
            $updateCommand='Get-WindowsUpdate -AcceptAll -MicrosoftUpdate -Install -IgnoreReboot'+$(if($notCategory){' -NotCategory '+$notCategory})
        }else{
            $updateCommand='Get-WindowsUpdate -AcceptAll -Install -IgnoreReboot'+$(if($notCategory){' -NotCategory '+$notCategory})
        }
        Invoke-Expression $updateCommand
             
        $pendingReboot=checkPendingReboot $computer
        if(!$pendingReboot){
            write-host 'Updates are completed.' -ForegroundColor Green
            return $true
        }else{
            write-host 'Please reboot and trigger updates again to complete the process.' -ForegroundColor Yellow
            return $false
            }        
        }
 
    function checkUpdates($microsoftUpdates,$notCategory='drivers',$verbose=$false){
        ## This runs into the constraints of unelevated process being prevented from reading stdout of an elevated session
        ## Source: https:// docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process?view=netcore-3.1 
        #$startInfo = New-Object System.Diagnostics.ProcessStartInfo
        #$startInfo.FileName = $exe
        #$startInfo.RedirectStandardError = $true
        #$startInfo.RedirectStandardOutput = $true    
        #$startInfo.Arguments = "(Get-wulist -verbose).kb.count"
        #$startInfo.CreateNoWindow = $false
        #$startInfo.UseShellExecute = $false
        ##$startInfo.Verb = "runas"
        ##$startInfo.UseShellExecute = $true
        ##Error when trying to run as Administrator: Exception calling 'Start' with "0" argument(s):
        ## 'The Process object must have the UseShellExecute property set to false in order to redirect IO streams.'
        #$process = New-Object System.Diagnostics.Process
        #$process.StartInfo = $startInfo
        #$process.Start()
        #$process.WaitForExit()
        #$stdout = $process.StandardOutput.ReadToEnd()
        #$stderr = $process.StandardError.ReadToEnd()
        #Write-Host 'stdout: '+ $stdout
        #if($stderr){Write-Host 'stderr: '+$stderr -ForegroundColor Red}
        #Write-Host 'exit code: '+$($process.ExitCode)
        #return $stdout
        #
        # This is the workaround
        $tempDir='C:\temp\'
        if(Test-Path $tempDir){$null=mkdir $tempDir -force}
        $tempFile='C:\temp\availableUpdatesCount.txt'
        $checkUpdates=@"
            `$x=(Get-wulist -verbose $(if($microsoftUpdates){'-MicrosoftUpdate '}) $(if($notCategory){'-NotCategory '+$notCategory})).kb.count
            write-host `$x
            New-Item '$tempFile' -ItemType File -Value `$x -Force
"@
        Start-Process -verb Runas powershell.exe $checkUpdates -Wait -WindowStyle $(if($verbose){'normal'}else{'minimized'})
        $result=Get-Content $tempFile
        Start-Process -verb Runas powershell.exe "remove-item '$tempFile' -Force" -WindowStyle hidden -Wait 
        return $result
    }
 
    $functionScript = @"
        `$Host.UI.RawUI.BackgroundColor = 'Black'
        `$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
        `$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal(`$myWindowsID)
        `$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
        if (`$myWindowsPrincipal.IsInRole(`$adminRole)){
            write-host "This session is running under the context of the system 'Administrator'" -ForegroundColor Green
        }else{
            write-warning "This session is NOT in the context of 'Administrator'"
            }
        Function checkPendingReboot{
            $(Get-Command checkPendingReboot|Select -expand Definition)
        }
        Function updateWindows{
            $(Get-Command updateWindows|Select -expand Definition)
        }
        updateWindows $microsoftUpdates $notCategory
"@
    
    write-host "Spawning a background process to update Windows as Administrator..."
    do{
        $process=Start-Process -verb Runas powershell $functionScript -WindowStyle $(if($verbose){'normal'}else{'minimized'}) -PassThru
        $lineBreak=60
        $dotCount=0
        $minute=0
        write-host "Minute`r`n$minute`t:" -NoNewline -ForegroundColor Yellow
        do {
            if($dotCount++ -lt $lineBreak){
                write-host '.' -NoNewline
            }else{
                $minute++
                write-host "`r`n$minute`t:" -ForegroundColor Yellow -NoNewline
                $dotCount=0
                }
            Start-Sleep -s 1
        }until (!$process.Responding)
 
        [bool]$isPendingReboot=checkPendingReboot
        [int]$updatesAvailable=checkUpdates $microsoftUpdates $notCategory $verbose
        if(!$updatesAvailable){
            write-host "`r`nWindows updates completed" -ForegroundColor Green        
            $completed=$true
        }else{ 
            write-host "`r`nMissing $updatesAvailable updates." -ForegroundColor Yellow
            $completed=$false
            }
    }until($completed -or $isPendingReboot)
    
    if($verbose){
        $minutes=[math]::round($localTimer.Elapsed.TotalMinutes,2)
        write-host "$minutes minutes elapsed"
    }
    if($isPendingReboot){
        write-host "`r`nPending reboots detected." -ForegroundColor Yellow
        return $false
    }elseif($completed){
        return $true
    }
}

updateLocalWindows -microsoftUpdates $true

# Optimize disk space

function cleanWindowsSherver{
    write-host 'Disabling Windows Media (a vector of attack surface from malware)'
    Disable-WindowsOptionalFeature –FeatureName "WindowsMediaPlayer" -Online
 
    write-host 'Disabling XPS...'
    Disable-WindowsOptionalFeature -Online -FeatureName "Printing-XPSServices-Features"
 
    write-host 'Removing Workfolder Client'
    Disable-WindowsOptionalFeature -Online -FeatureName "WorkFolders-Client"
 
    write-host 'Removing Windows Store'
    Get-AppxPackage -AllUsers | Where-Object {$_.Name -like "Microsoft.WindowsStore*"} | remove-appxpackage
 
    write-host "Clear Windows Update Cache..."
    Dism.exe /online /Cleanup-Image /StartComponentCleanup
 
    write-host "Delete files in Temp directory..."
    $null=del C:\Temp\*.* -Recurse -Force
 
    write-host "Prune Event Logs..."
    $null=wevtutil el | Foreach-Object {wevtutil cl "$_"}
 
    write-host "Disabling Automatic Startup Repair..."
    $null=cmd.exe /c "bcdedit /set {default} recoveryenabled No"
    $null=cmd.exe /c "bcdedit /set {default} bootstatuspolicy ignoreallfailures"

    write-host 'Disabling the annoying Windows Update notifications...'
    $system32="$env:windir\System32"
    $annoyingNotifications="$system32\musnotification.exe","$system32\musnotificationux.exe"
    $denyExecute= New-Object System.Security.AccessControl.FileSystemAccessRule("Everyone","Execute","Deny")
    $annoyingNotifications|%{
        $acl = Get-ACL $_
        $acl.AddAccessRule($denyExecute)
        Set-Acl $_ $acl
        }
    write-host "Performing Disk Cleanup..."
    (Get-Volume).DriveLetter|ForEach-Object{cleanmgr /d $_ /VeryLowDisk}
}
cleanWindowsSherver

# Uninstall WinDefend
Remove-WindowsFeature Windows-Defender, Windows-Defender-GUI
# Reset Windows SID
C:\Windows\System32\Sysprep\sysprep.exe /generalize
# updateLocalWindows_v0.0.3.ps1
# This function will quickly patch the local Windows machine
# There are two options:
#- Windows Update: will only patch the Windows Operating System
#- Microsoft Update (default): will patch all Microsoft products detected on the system
#- This version will 

function updateLocalWindows($microsoftUpdate=$true,$verbose=$true){

    function checkPendingReboot{
            param([string]$computer=$ENV:computername) 
            function checkRegistryPendingReboot{
                    if (Get-ChildItem 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending' -EA Ignore) { return $true }
                    if (Get-Item 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired' -EA Ignore) { return $true }
                    if (Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Name PendingFileRenameOperations -EA Ignore) { return $true }
                    try { 
                    $util = [wmiclass]'\\.\root\ccm\clientsdk:CCM_ClientUtilities'
                    $status = $util.DetermineIfRebootPending()
                    if(($status -ne $null) -and $status.RebootPending){
                        return $true
                    }
                    }catch{}
                    return $false           
            }
            return checkRegistryPendingReboot
        }

    function updateWindows($microsoftUpdate){
        #Install the PowerShell Windows Update module
        $checkModule=Get-Module -ListAvailable -Name PSWindowsUpdate
        if(!($checkModule)){
            [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
            # Set PowerShell Gallery as Trusted to bypass prompts
            $trustPSGallery=(Get-psrepository -Name 'PSGallery').InstallationPolicy
            If($trustPSGallery -ne 'Trusted'){
                Install-PackageProvider -Name Nuget -Force
                Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted -Confirm:$false
                }        
            Install-Module PSWindowsUpdate -Confirm:$false
            }
 
        # Perform Updates
        set-executionpolicy bypass -force
        if($microsoftUpdate){
            # Register Microsoft Update Service if it has not been registered
            $microsoftUpdateId='7971f918-a847-4430-9279-4a52d1efe18d'
            $registered=$microsoftUpdateId -in (Get-WUServiceManager).ServiceID
            if (!($registered)){
                Add-WUServiceManager -ServiceID $microsoftUpdateId -Confirm:$false
                }
            Get-WindowsUpdate -AcceptAll -MicrosoftUpdate -Install -IgnoreReboot
        }else{
            Get-WindowsUpdate -AcceptAll -WindowsUpdate -Install -IgnoreReboot
            }
        $pendingReboot=checkPendingReboot
        if(!$pendingReboot){
            write-host 'Updates are completed.' -ForegroundColor Green
            return $true
        }else{
            write-host 'Please reboot and trigger updates again to complete the process.' -ForegroundColor Yellow
            return $false
            }        
        }

    function isLocalAdmin{
        $myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
        $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
        $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
        if ($myWindowsPrincipal.IsInRole($adminRole)){
           $Host.UI.RawUI.BackgroundColor = "Black"
           clear-host
           Write-Host "Running in the context of Local Administrator..." -ForegroundColor Green
           return $true
        }else{
            clear-host
            Write-Host "NOT Running in the context of Local Administrator..." -ForegroundColor Yellow
            return $false
           }
    }

    $functionScript = @"
        `$Host.UI.RawUI.BackgroundColor = 'Black'
        `$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
        `$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal(`$myWindowsID)
        `$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
        if (`$myWindowsPrincipal.IsInRole(`$adminRole)){
            write-host "This session is running under the context of the system 'Administrator'" -ForegroundColor Green
        }else{
            write-warning "This session is NOT in the context of 'Administrator'"
            }
        Function checkPendingReboot{
            $(Get-Command checkPendingReboot|Select -expand Definition)
        }
        Function updateWindows{
            $(Get-Command updateWindows|Select -expand Definition)
        }
        updateWindows $microsoftUpdate
"@
    $null=isLocalAdmin    
    write-host "Spawning a new process to update Windows as Administrator..."
    
    if($verbose){
        $process=Start-Process -verb Runas powershell $functionScript -PassThru
    }else{
        $process=Start-Process -verb Runas powershell $functionScript -WindowStyle hidden -PassThru
        }
    
    $lineBreak=60
    $dotCount=0
    $minute=0
    write-host "Minute`r`n$minute`t:" -NoNewline -ForegroundColor Yellow
    do {
        if($dotCount++ -lt $lineBreak){
            write-host '.' -NoNewline
        }else{
            $minute++
            write-host "`r`n$minute`t:" -ForegroundColor Yellow
            $dotCount=0
            }
        Start-Sleep -s 1
    }until (!$process.Responding)

    if(!(checkPendingReboot)){
        write-host "`r`nWindows updates completed" -ForegroundColor Green
        return $true
    }else{
        write-host "`r`nPending reboots detected." -ForegroundColor Yellow
        return $false
        }
}

updateLocalWindows
# updateLocalWindows_v0.0.2.ps1
# This function will quickly patch the local Windows machine
# There are two options:
#- Windows Update: will only patch the Windows Operating System
#- Microsoft Update (default): will patch all Microsoft products detected on the system

function updateLocalWindows($microsoftUpdate=$true){

    function checkPendingReboot{
            param([string]$computer=$ENV:computername) 
            function checkRegistryPendingReboot{
                 if (Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending" -EA Ignore) { return $true }
                 if (Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" -EA Ignore) { return $true }
                 if (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name PendingFileRenameOperations -EA Ignore) { return $true }
                 try { 
                   $util = [wmiclass]"\\.\root\ccm\clientsdk:CCM_ClientUtilities"
                   $status = $util.DetermineIfRebootPending()
                   if(($status -ne $null) -and $status.RebootPending){
                     return $true
                   }
                 }catch{}
                 return $false            
            }
            return checkRegistryPendingReboot
        }

    #Install the PowerShell Windows Update module
    $checkModule=Get-Module -ListAvailable -Name PSWindowsUpdate
    if(!($checkModule)){
        [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
        # Set PowerShell Gallery as Trusted to bypass prompts
        $trustPSGallery=(Get-psrepository -Name 'PSGallery').InstallationPolicy
        If($trustPSGallery -ne 'Trusted'){
            Install-PackageProvider -Name Nuget -Force
            Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted -Confirm:$false
            }        
        Install-Module PSWindowsUpdate -Confirm:$false
        }

    # Perform Updates
    set-executionpolicy bypass -force
    if($microsoftUpdate){
        # Register Microsoft Update Service if it has not been registered
        $MicrosoftUpdateID="7971f918-a847-4430-9279-4a52d1efe18d"
        $registered=$MicrosoftUpdateID -in (Get-WUServiceManager).ServiceID
        if (!($registered)){
            Add-WUServiceManager -ServiceID 7971f918-a847-4430-9279-4a52d1efe18d -Confirm:$false
            }
        Get-WindowsUpdate -AcceptAll -MicrosoftUpdate -Install -IgnoreReboot
    }else{
        Get-WindowsUpdate -AcceptAll -WindowsUpdate -Install -IgnoreReboot
        }
    $pendingReboot=checkPendingReboot
    if(!$pendingReboot){
        write-host "$env:computername updates are completed." -ForegroundColor Green
        return $true
    }else{
        write-host "Please reboot $env:computername and run updates again to complete the process." -ForegroundColor Yellow
        return $false
        }
}

updateLocalWindows;

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Post

Python: Package Installer for Python (PIP)

This comes preinstalled with Python 3.4 or higher. Similar to the Microsoft PowerShell Gallery, Python.org…

Use CSS Override to Modify WordPress 2016 Theme

August 28th, 2020 update Modifications: 1. Move search bar to top right Edit header.php: Dashboard…

PowerShell: Activate Remote Windows

$remoteWindows="SHERVER01","SHERVER02"$licenseKey="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX"function activateWindows{ param( [string]$key ) $licensingService = get-wmiObject -query "select * from SoftwareLicensingService" -computername $env:computername;…