SILENT WINDOWS PATCHING AND CONTROLLED REBOOTS
updating windows and control when the system restarts.
Thanks to Rönnkvist
Thanks to Rönnkvist
Copy the following files to %ProgramFiles%\RebootIfNeeded
RebootIfNeeded.ps1 – Copy script below
hstart64.exe – Download from http://www.ntwind.com/software/hstart.html (needed to hide the scheduled task completely)
ShutdownTool.exe – Download from http://blog.coretech.dk/kea/new-version-of-the-coretech-shutdown-tool/ (you can find the latest version in the comments)
Create a Scheduled Task that runs once or twice every day (I have it set at 08:00 and 13:00 every weekday), and on that task create an with the following configuration:
Program: %ProgramFiles%\RebootIfNeeded\hstart64.exe
Arguments: /NOCONSOLE /WAIT “”%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe” -NoLogo -NoProfile -NonInteractive -File “%ProgramFiles%\RebootIfNeeded\RebootIfNeeded.ps1″”
hstart64.exe – Download from http://www.ntwind.com/software/hstart.html (needed to hide the scheduled task completely)
ShutdownTool.exe – Download from http://blog.coretech.dk/kea/new-version-of-the-coretech-shutdown-tool/ (you can find the latest version in the comments)
Create a Scheduled Task that runs once or twice every day (I have it set at 08:00 and 13:00 every weekday), and on that task create an with the following configuration:
Program: %ProgramFiles%\RebootIfNeeded\hstart64.exe
Arguments: /NOCONSOLE /WAIT “”%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe” -NoLogo -NoProfile -NonInteractive -File “%ProgramFiles%\RebootIfNeeded\RebootIfNeeded.ps1″”
[CmdletBinding()] PARAM ( $maxBootAgeDays = 35, $restartTimeOut = (9 * 60), # 9 hours $restartMaxPostpone = (48 * 60), # 48 hours $restartDescriptions = @{ "en-US" = "Your computer needs to restart to receive the latest updates."; }, $defaultLanguage = "en-US" ) Function Get-PendingReboot { # Local HKLM $HKLM = [UInt32] "0x80000002" $wmiRegistry = [WMIClass] "\\.\root\default:StdRegProv" #Default $PendingReboot = $false # CBS - Reboot Required ? $RegSubKeysCBS = $wmiRegistry.EnumKey($HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\") if ($RegSubKeysCBS.sNames -contains "RebootPending") { Write-Verbose "Component Based Servicing have a reboot pending" $PendingReboot = $true } # Windows Update - Reboot Required? $RegistryWUAU = $wmiRegistry.EnumKey($HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\") if ($RegistryWUAU.sNames -contains "RebootRequired") { Write-Verbose "Windows Update have a reboot required" $PendingReboot = $true } ## Pending FileRenameOperations ? $RegSubKeySM = $wmiRegistry.GetMultiStringValue($HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\","PendingFileRenameOperations") If ($RegSubKeySM.sValue) { $RegSubKeySM.sValue | ForEach-Object { If ($_.Trim() -ne '') { Write-Verbose "Pending FileRename operation: $($_)" } } $PendingReboot = $true } # ConfigMgr - Pending reboot ? TRY { $CCMClientSDK = Invoke-WmiMethod -NameSpace "ROOT\ccm\ClientSDK" -Class "CCM_ClientUtilities" -Name "DetermineIfRebootPending" -ErrorAction Stop If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending) { Write-Verbose "ConfigMgr have reboot pending" $PendingReboot = $true } } CATCH { Write-Verbose "Cant talk to ConfigMgr Agent" } Write-Verbose "Pending reboot: $($PendingReboot)" Return $PendingReboot } Function Check-OldBootAge { PARAM ( $maxAgeDays = 35 ) $BootTime = Get-WmiObject Win32_Operatingsystem [Int]$days = (New-TimeSpan -Start $boottime.ConvertToDateTime($boottime.LastBootUpTime) -End (Get-Date)).TotalDays if ($days -ge $maxAgeDays) { Write-Verbose "Boot age is $($days) days (more than $($maxBootAgeDays)), reboot required" Return $true } else { Write-Verbose "Boot age is $($days) days (less than $($maxBootAgeDays))" Return $false } Return $days } Function Get-UserLanguage { Return [String] ([System.Threading.Thread]::CurrentThread).CurrentUICulture.Name } # ------------------------------------------------------------------------------------------------------------ # Main script if ( (Get-WmiObject -Query "SELECT ProductType FROM Win32_OperatingSystem").ProductType -eq 1) { If ( (Get-Process "ShutdownTool" -ErrorAction SilentlyContinue) ) { Write-Host "Already running ShutdownTool" } else { If ((Check-OldBootAge -maxAgeDays $maxBootAgeDays) -or (Get-PendingReboot)) { Write-Host "Reboot is required, calling restart utility" $userLanguage = Get-UserLanguage Write-Verbose "Language: $($userLanguage)" # Find description $Description = $restartDescriptions[$userLanguage] if ($Description -eq $null) { $Description = $restartDescriptions[$defaultLanguage] } $timeOutSeconds = ($restartTimeOut*60) - 1 Write-Verbose "Restart timeout: $($timeOutSeconds) seconds" Write-Verbose "Max postpone: $($restartMaxPostpone) minutes" Write-Verbose "Description: $($Description)" If ((Test-Path ".\ShutdownTool.exe") -eq $false) { Throw "Cant find ShutdownTool.exe" } else { Write-Verbose "Calling restart with ShutdownTool" .\ShutdownTool.exe /g:$userLanguage /d:"$Description" /t:$timeOutSeconds /m:$restartMaxPostpone /r /c } # /g - Language # /d - description # /t - countdown in sec # /m - max postpone in min # /r - reboot instead of shutdown # /c - force & remove abort-btn } } } else { Write-Verbose "Not a client OS" } # Done!
Spiceworks Link
https://community.spiceworks.com/scripts/show/3706-silent-windows-patching-and-controlled-reboots