La diagnosi dei problemi di Windows Update può essere un compito noioso per i professionisti IT, soprattutto quando si gestiscono più macchine. Ritardi o errori nel processo di aggiornamento possono portare a vulnerabilità di sicurezza, problemi di conformità e instabilità generale del sistema.
Lo script PowerShell fornito offre un approccio semplificato per diagnosticare e risolvere i problemi comuni di Windows Update, garantendo che i sistemi rimangano aggiornati e sicuri. In questo articolo si approfondiscono le funzionalità dello script per la diagnosi dei problemi di Windows Update opera eseguendo una serie di controlli sui principali componenti e servizi di Windows Update, e si discute di come lo script possa essere uno strumento prezioso per i professionisti IT e i Managed Service Provider (MSP).
Background
Windows Update è un componente fondamentale per mantenere l’integrità e la sicurezza di un sistema basato su Windows. Tuttavia, diversi fattori possono ostacolarne il buon funzionamento, dalle configurazioni errate dei servizi ai problemi di rete. I professionisti IT devono spesso affrontare l’arduo compito di risolvere questi problemi manualmente, processo che può richiedere molto tempo ed essere soggetto a errori umani.
Lo script PowerShell per la diagnosi dei problemi di Windows Update opera eseguendo una serie di controlli sui principali componenti e servizi di Windows Update fornito affronta questa sfida automatizzando il processo di diagnostica, e assicurando che i problemi più comuni vengano identificati e risolti rapidamente. Utilizzando questo script, i team IT possono mantenere l’integrità del sistema, ridurre i tempi di inattività e migliorare l’efficienza complessiva.
Lo script per la diagnosi dei problemi di Windows Update:
#Requires -Version 5.1 <# .SYNOPSIS Diagnose Windows Update issues. .DESCRIPTION Checks that CryptSvc, and bits or running or not Checks that wuauserv is running and the startup type is set correctly. Checks WaaSMedic plugins doesn't have issues. (Only applies to OS Build Version is greater than 17600). Checks if NTP is setup. Checks Windows Update logs for any errors in the last week. .EXAMPLE (No Parameters) ## EXAMPLE OUTPUT WITHOUT PARAMS ## [Info] Last checked for updates on 4/29/2023 [Issue] Windows Update has not checked for updates in over 30 days. PARAMETER: -ResultsCustomField WindowsUpdate Saves results to a multi-line custom field. .EXAMPLE -ResultsCustomField WindowsUpdate ## EXAMPLE OUTPUT WITH ResultsCustomField ## [Info] Last checked for updates on 4/29/2023 [Issue] Windows Update has not checked for updates in over 90 days. .OUTPUTS None .NOTES Minimum OS Architecture Supported: Windows 10, Windows Server 2016 Release Notes: Initial Release By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://ninjastage2.wpengine.com/terms-of-use. Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA). #> [CmdletBinding()] param ( [int]$Days = 30, [string]$ResultsCustomField ) begin { if ($env:Days) { $Days = $env:Days } if ($env:resultscustomfield -notlike "null") { $ResultsCustomField = $env:resultscustomfield } function Test-IsElevated { $id = [System.Security.Principal.WindowsIdentity]::GetCurrent() $p = New-Object System.Security.Principal.WindowsPrincipal($id) $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator) } function Test-WaaSMedic { [CmdletBinding()] param() $WaaS = 0 Try { $WaaS = New-Object -ComObject "Microsoft.WaaSMedic.1" } Catch { Write-Host "WaaS Medic Support: No" } Try { if ($WaaS -ne 0) { Write-Host "WaaS Medic Support: Yes" $Plugins = $WaaS.LaunchDetectionOnly("Troubleshooter") if ($Plugins -eq "") { [PSCustomObject]@{ Id = "WaaSMedic" Detected = $false Parameter = @{"error" = $Plugins } } } else { [PSCustomObject]@{ Id = "WaaSMedic" Detected = $true Parameter = @{"error" = $Plugins } } "Plugins that might have errors: " + $Plugins | Out-String | Write-Host } } } Catch { Write-Host "WaaS Medic Detection: Failed" } Finally { # Release COM Object if we aren't running test cases if (-not $env:NinjaPesterTesting) { [System.Runtime.Interopservices.Marshal]::ReleaseComObject($WaaS) | Out-Null } } } function Get-TimeSyncType { [string]$result = "" [string]$registryKey = "HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\Parameters" [string]$registryKeyName = "Type" if ((Test-Path $registryKey -ErrorAction SilentlyContinue)) { $registryEntry = Get-Item -Path $registryKey -ErrorAction SilentlyContinue if ($null -ne $registryEntry) { return Get-ItemPropertyValue -Path $registryKey -Name $registryKeyName } } return $result } function Test-ConnectedToInternet { $NLMType = [Type]::GetTypeFromCLSID('DCB00C01-570F-4A9B-8D69-199FDBA5723B') $INetworkListManager = [Activator]::CreateInstance($NLMType) return ($INetworkListManager.IsConnectedToInternet -eq $true) } function Get-ComponentAndErrorCode([string]$msg) { $Codes = [regex]::matches($msg, "0x[a-f0-9a-f0-9A-F0-9A-F0-9]{6,8}") if ($Codes.count -gt 1) { $CodeList = "" # there can be more than one error code can be returned for the same component at once foreach ($Code in $Codes) { $CodeList += "_" + $Code } return $CodeList } else { return $Codes[0].Value } } function Get-DatedEvents($EventLog) { $DatedEvents = @() if ($null -eq $EventLog) { return $null } foreach ($Event in $EventLog) { #$eventMsg = $event.Message $DatedEvents += $Event.Message } return $DatedEvents } function Get-SystemEvents($EventSrc, $Time) { $Events = Get-WinEvent -ProviderName $EventsSrc -ErrorAction 0 | Where-Object { ($_.LevelDisplayName -ne "Information") -and (($_.Id -eq 20) -or ($_.Id -eq 25)) -and ($_.TimeCreated -gt $Time) } return $Events } function Get-HasWinUpdateErrorInLastWeek([switch]$AllLastWeekError) { $Events = @() $EventsSrc = "Microsoft-Windows-WindowsUpdateClient" $startTime = (Get-Date) - (New-TimeSpan -Day 8) $wuEvents = Get-SystemEvents $EventsSrc $startTime if ($null -eq $wuEvents) { return $null } $Events += Get-DatedEvents $wuEvents $LatestError = Get-ComponentAndErrorCode $Events[0] $ErrorList = @{} $ErrorList.add("latest", $LatestError) if ($AllLastWeekError) { foreach ($str in $Events) { $ECode = Get-ComponentAndErrorCode $str if ($null -ne $ECode -and !$ErrorList.ContainsValue($ECode)) { $ErrorList.add($ECode, $ECode) } } } return $ErrorList } Function Get-LocalTime($UTCTime) { $strCurrentTimeZone = (Get-CimInstance -ClassName Win32_TimeZone).StandardName # If running test cases return current date if ($env:NinjaPesterTesting) { return Get-Date } $TZ = [System.TimeZoneInfo]::FindSystemTimeZoneById($strCurrentTimeZone) Return [System.TimeZoneInfo]::ConvertTimeFromUtc($UTCTime, $TZ) } $IssuesFound = $false $Log = [System.Collections.Generic.List[String]]::new() } process { if (-not (Test-IsElevated)) { Write-Error -Message "Access Denied. Please run with Administrator privileges." exit 1 } if (-not $(Test-ConnectedToInternet)) { Write-Host "[Issue] Windows doesn't think it is connected to Internet." $IssuesFound = $true } # Check CryptSvc amd bits services $Service = Get-Service -Name CryptSvc if ($Service.StartType -notlike 'Automatic') { Write-Host "[Issue] (CryptSvc) CryptSvc service is set to $($Service.StartType) but needs to be set to Automatic" $Log.Add("[Issue] (CryptSvc) CryptSvc service is set to $($Service.StartType) but needs to be set to Automatic") $IssuesFound = $true } else { Write-Host "[Info] (CryptSvc) CryptSvc service is set to $($Service.StartType)" $Log.Add("[Info] (CryptSvc) CryptSvc service is set to $($Service.StartType)") } $Service = Get-Service -Name bits if ($Service.StartType -eq 'Disabled') { Write-Host "[Issue] (bits) BITS service is set to $($Service.StartType) but needs to be set to Manual" $Log.Add("[Issue] (bits) BITS service is set to $($Service.StartType) but needs to be set to Manual") $IssuesFound = $true } else { Write-Host "[Info] (bits) BITS service is set to $($Service.StartType)" $Log.Add("[Info] (bits) BITS service is set to $($Service.StartType)") } # Check that Windows Update service is running and isn't disabled $wuService = Get-Service -Name wuauserv -ErrorAction SilentlyContinue if ($wuService.Status -ne "Running") { $Service = Get-Service -Name wuauserv if ($Service.StartType -eq 'Disabled') { Write-Host "[Issue] (wuauserv) Windows Update service is set to $($Service.StartType) but needs to be set to Automatic (Trigger Start) or Manual" $Log.Add("[Issue] (wuauserv) Windows Update service is set to $($Service.StartType) but needs to be set to Automatic (Trigger Start) or Manual") $IssuesFound = $true } else { Write-Host "[Info] (wuauserv) Windows Update service is set to $($Service.StartType)" $Log.Add("[Info] (wuauserv) Windows Update service is set to $($Service.StartType)") } } # Check WaaSMedic $SupportWaaSMedic = [System.Environment]::OSVersion.Version.Build -gt 17600 if ($SupportWaaSMedic) { $Plugins = Test-WaaSMedic $PluginIssues = $Plugins | Where-Object { $_.Parameter["error"] } | ForEach-Object { $PluginErrors = $_.Parameter["error"] "[Potential Issue] WaaSMedic plugin errors found with: $($PluginErrors)" } if ($PluginIssues.Count -gt 1) { Write-Host "[Issue] Found more than 1 plugin errors." $Log.Add("[Issue] Found more than 1 plugin errors.") $PluginIssues | Write-Host $IssuesFound = $true } } # Check if NTP is setup if ("NoSync" -eq (Get-TimeSyncType)) { Write-Host "[Issue] NTP not setup!" $Log.Add("[Issue] NTP not setup!") $IssuesFound = $true } # Check Windows Update logs $EventErrors = Get-HasWinUpdateErrorInLastWeek -AllLastWeekError if ($EventErrors.Count -gt 0) { if (![string]::IsNullOrEmpty($allError.Values)) { Write-Host "[Issue] Event Log has Windows Update errors." $Log.Add("[Issue] Event Log has Windows Update errors.") $errorCodes = $allError.Values -join ';' Write-Host "[Issue] Error codes found: $errorCodes" $Log.Add("[Issue] Error codes found: $errorCodes") $IssuesFound = $true } } # If no issues found, get number of days since the last check for updates happened if (-not $IssuesFound) { $LastCheck = Get-LocalTime $(New-Object -ComObject Microsoft.Update.AutoUpdate).Results.LastSearchSuccessDate Write-Host "[Info] Last checked for updates on $($LastCheck.ToShortDateString())" $Log.Add("[Info] Last checked for updates on $($LastCheck.ToShortDateString())") $LastCheckTimeSpan = New-TimeSpan -Start $LastCheck -End $(Get-Date) if ($LastCheckTimeSpan.TotalDays -gt $Days) { $Days = [System.Math]::Round($LastCheckTimeSpan.TotalDays, 0) Write-Host "[Issue] Windows Update has not checked for updates in over $Days days." $Log.Add("[Issue] Windows Update has not checked for updates in over $Days days.") $IssuesFound = $true } } if ($ResultsCustomField) { Ninja-Property-Set -Name $ResultsCustomField -Value $($Log | Out-String) } if ($IssuesFound) { exit 1 } exit 0 } end { }
Analisi dettagliata
Lo script per la diagnosi dei problemi di Windows Update opera eseguendo una serie di controlli sui principali componenti e servizi di Windows Update, ognuno dei quali è essenziale per il corretto funzionamento del processo di aggiornamento. Ecco una descrizione passo per passo di come funziona lo script:
1. Controllo dell’elevazione dei permessi: Lo script per la diagnosi dei problemi di Windows Update inizia verificando che venga eseguito con i privilegi di amministratore, necessari per modificare i servizi di sistema e accedere a registri specifici.
2. Test di connettività Internet: Controlla se il sistema è connesso a Internet, un requisito fondamentale per scaricare gli aggiornamenti.
3. Controlli dello stato dei servizi:
- Cryptographic Services (CryptSvc): Assicura che i Cryptographic Service siano impostati su “Automatico”, una configurazione necessaria per gestire i file di aggiornamento in modo sicuro.
- Background Intelligent Transfer Service (BITS): Verifica che BITS non sia disattivato, poiché è responsabile del trasferimento dei file in background, compresi gli aggiornamenti.
- Windows Update Service (wuauserv): Conferma che Windows Update service sia in esecuzione e impostato sul tipo di avvio corretto.
4. Verifica di WaaSMedic: Per i sistemi con una versione di build superiore a 17600, lo script per la diagnosi dei problemi di Windows Update controlla i plugin WaaSMedic, che sono responsabili della correzione automatica dei problemi legati all’aggiornamento.
5. Configurazione NTP: Lo script per la diagnosi dei problemi di Windows Update controlla se il Network Time Protocol (NTP) sia configurato correttamente, assicurando che l’orologio del sistema sia sincronizzato con una fonte di tempo esterna, un fattore cruciale per il processo di aggiornamento.
6. Analisi del registro eventi: Esamina i registri eventi di Windows Update alla ricerca di eventuali errori registrati nell’ultima settimana, identificando codici di errore specifici che possono indicare problemi di fondo.
7. Verifica dell’ultimo aggiornamento: Infine, lo script per la diagnosi dei problemi di Windows Update determina l’ultima volta che il sistema ha verificato la presenza di aggiornamenti. Se supera la soglia definita dall’utente (l’impostazione predefinita è 30 giorni), il problema viene segnalato.
Ognuno di questi controlli viene registrato e, se vengono riscontrati problemi, vengono riportati in un riepilogo che può essere salvato in un campo personalizzato per ulteriori analisi.
Casi d’uso potenziali
Immagina un professionista IT che gestisce una serie di workstation per una grande azienda. Un giorno, alcuni utenti segnalano che i loro sistemi non ricevono aggiornamenti da diverse settimane. Invece di controllare manualmente ogni sistema, il professionista IT distribuisce questo script per la diagnosi dei problemi di Windows Update su tutte le stazioni di lavoro.
Lo script identifica che il servizio Windows Update su diversi computer è configurato in modo errato e che il BITS è disabilitato su altri. Evidenzia inoltre che alcuni sistemi non verificano la presenza di aggiornamenti da oltre 60 giorni.
Con queste informazioni, il professionista IT può correggere rapidamente i problemi, assicurando che tutti i sistemi siano aggiornati, riducendo al minimo i rischi per la sicurezza e mantenendo la conformità con le policy aziendali.
Confronti
Questo script PowerShell offre un approccio più automatizzato e completo rispetto ai metodi tradizionali per la diagnosi dei problemi di Windows Update, come il controllo manuale degli stati dei servizi o la verifica dei registri degli eventi.
Sebbene strumenti basati su GUI come Windows Update Troubleshooter possano risolvere alcuni problemi, spesso non sono in grado di fornire informazioni dettagliate o di gestire più macchine contemporaneamente.
Questo script, invece, non solo identifica i problemi, ma offre anche approfondimenti chiari e utilizzabili, il che lo rende un’opzione migliore per gli ambienti IT su larga scala.
Domande frequenti
1. Questo script può risolvere i problemi che trova?
- No, questo script è progettato per diagnosticare e segnalare i problemi. Tuttavia, fornisce informazioni sufficienti ai professionisti IT per permettergli di adottare le misure necessarie a risolvere i problemi manualmente.
2. Questo script per la diagnosi dei problemi di Windows Update è compatibile con tutte le versioni di Windows?
- Lo script per la diagnosi dei problemi di Windows Update supporta Windows 10 e Windows Server 2016 e versioni successive, garantendo un’ampia applicabilità negli ambienti Windows moderni.
3. Cosa devo fare se lo script segnala un errore con i plugin WaaSMedic?
- I problemi legati a WaaSMedic richiedono in genere un intervento manuale. Potrebbe essere necessario ripristinare il servizio WaaSMedic o utilizzare strumenti aggiuntivi per risolvere gli errori specifici del plugin.
Implicazioni
I risultati di questo script per la diagnosi dei problemi di Windows Update possono avere implicazioni significative per la sicurezza informatica. Identificare e risolvere tempestivamente i problemi di Windows Update può impedire che le vulnerabilità non patchate vengano sfruttate, riducendo il rischio di attacchi informatici.
Inoltre, garantire che gli aggiornamenti siano applicati in modo coerente aiuta a mantenere la stabilità del sistema, evitando interruzioni impreviste che potrebbero interrompere le operazioni aziendali.
Raccomandazioni
Quando utilizzi questo script per la diagnosi dei problemi di Windows Update, ricordati di:
- Eseguirlo regolarmente: Incorporalo nel tuo programma di manutenzione ordinaria per garantire che i problemi legati agli aggiornamenti vengano individuati tempestivamente.
- Analizzare attentamente i log: Presta attenzione ai dettagli dei log generati dallo script per la diagnosi dei problemi di Windows Update, perché possono fornire informazioni critiche sui problemi ricorrenti.
- Integrarlo con strumenti di automazione: Per gli ambienti su larga scala, prendi in considerazione la possibilità di integrare questo script per la diagnosi dei problemi di Windows Update con piattaforme di automazione come NinjaOne, per semplificare il processo diagnostico su più sistemi.
Considerazioni finali
NinjaOne offre una potente piattaforma che fungere da complemento alle funzionalità di questo script per la diagnosi dei problemi di Windows Update. Integrando lo script nei flussi di lavoro automatizzati di NinjaOne, i professionisti IT possono migliorare la loro capacità di diagnosticare e risolvere i problemi di Windows Update su numerosi computer contemporaneamente.
Questa integrazione non solo fa risparmiare tempo, ma garantisce anche che tutti i sistemi rimangano sicuri e aggiornati, contribuendo in ultima analisi a un’infrastruttura IT più stabile e resiliente.