Es ist auschlaggebend, dass Sie den Windows-Dienststatus überprüfen und das gute Funktionieren von Diensten auf Windows-Computern aufrechterhalten können. PowerShell ermöglicht dies Ihnen, damit Sie für einen reibungslosen Betrieb in jeder IT-Umgebung sorgen. Dienste, die so eingestellt sind, dass sie automatisch starten, aber nicht ausgeführt werden, können zu Leistungsproblemen, ungeplanten Netzwerkausfällen und betrieblichen Ineffizienzen führen.
An dieser Stelle kommen PowerShell-Skripte ins Spiel, die eine robuste und automatisierte Methode zur Verwaltung und Überwachung von Windows-Diensten bieten. In diesem Blogbeitrag wird ein PowerShell-Skript vorgestellt, mit dem automatische Dienste, die derzeit nicht ausgeführt werden, gemeldet und gestartet werden, mit Ausnahme von Diensten, für die ein ‘Verzögerter Start’ oder ‘Ausgelöster Start’ festgelegt ist.
Kontext
Für IT-Expert:innen und Managed Service Provider (MSPs) hat der reibungslose Betrieb von Diensten höchste Priorität. Windows-Dienste können manchmal aus verschiedenen Gründen nicht gestartet werden, zum Beispiel aufgrund von Konfigurationsproblemen, Konflikten oder begrenzten Systemressourcen.
Dieses Skript befasst sich mit der Notwendigkeit eines systematischen Ansatzes zur Identifizierung und zum Neustart von Diensten, die laufen sollten, aber nicht funktionieren. Durch die Automatisierung dieses Prozesses können IT-Teams Zeit sparen und das Risiko menschlichen Versagens verringern.
Das Skript zur Überprüfung des Status von Windows-Diensten
#Requires -Version 5.1 <# .SYNOPSIS Reports on or starts services for Automatic Services that are not currently running. Services set as 'Delayed Start' or 'Trigger Start' are ignored. .DESCRIPTION Reports on or starts services for Automatic Services that are not currently running. Services set as 'Delayed Start' or 'Trigger Start' are ignored. .EXAMPLE (No Parameters) Matching Services found! Name Description ---- ----------- SysMain Maintains and improves system performance over time. PARAMETER: -IgnoreServices "ExampleServiceName" A comma separated list of service names to ignore. PARAMETER: -StartFoundServices Attempts to start any services found matching the criteria. .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://www.ninjaone.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 ( [Parameter()] [String]$IgnoreServices, [Parameter()] [Switch]$StartFoundServices = [System.Convert]::ToBoolean($env:startFoundServices) ) begin { # Replace script parameters with form variables if($env:servicesToExclude -and $env:servicesToExclude -notlike "null"){ $IgnoreServices = $env:servicesToExclude } # Get the last startup time of the operating system. $LastBootDateTime = Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty LastBootUpTime if ($LastBootDateTime -gt $(Get-Date).AddMinutes(-15)) { $Uptime = New-TimeSpan $LastBootDateTime (Get-Date) | Select-Object -ExpandProperty TotalMinutes Write-Host "Current uptime is $([math]::Round($Uptime)) minutes." Write-Host "[Error] Please wait at least 15 minutes after startup before running this script." exit 1 } # Define a function to test if the current user has elevated (administrator) privileges. function Test-IsElevated { $id = [System.Security.Principal.WindowsIdentity]::GetCurrent() $p = New-Object System.Security.Principal.WindowsPrincipal($id) $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator) } $ExitCode = 0 } process { # Check if the script is running with Administrator privileges. if (!(Test-IsElevated)) { Write-Host -Object "[Error] Access Denied. Please run with Administrator privileges." exit 1 } # Define a string of characters that are invalid for service names. $InvalidServiceNameCharacters = "\\|/|:" # Create a list to hold the names of services to ignore. $ServicesToIgnore = New-Object System.Collections.Generic.List[string] # If there are services to ignore and they are separated by commas, split the string into individual service names. if ($IgnoreServices -and $IgnoreServices -match ",") { $IgnoreServices -split "," | ForEach-Object { # Check each service name for invalid characters or excessive length. if ($_.Trim() -match $InvalidServiceNameCharacters) { Write-Host "[Error] Service Name contains one of the invalid characters '\/:'. $_ is not a valid service to ignore." $ExitCode = 1 return } if (($_.Trim()).Length -gt 256) { Write-Host "[Error] Service Name is greater than 256 characters. $_ is not a valid service to ignore. " $ExitCode = 1 return } # Add valid services to the ignore list. $ServicesToIgnore.Add($_.Trim()) } } elseif ($IgnoreServices) { # For a single service name, perform similar validation and add if valid. $ValidService = $True if ($IgnoreServices.Trim() -match $InvalidServiceNameCharacters) { Write-Host "[Error] Service Name contains one of the invalid characters '\/:'. '$IgnoreServices' is not a valid service to ignore. " $ExitCode = 1 $ValidService = $False } if (($IgnoreServices.Trim()).Length -gt 256) { Write-Host "[Error] Service Name is greater than 256 characters. '$IgnoreServices' is not a valid service to ignore. " $ExitCode = 1 $ValidService = $False } if ($ValidService) { $ServicesToIgnore.Add($IgnoreServices.Trim()) } } # Create a list to hold non-running services that are set to start automatically. $NonRunningAutoServices = New-Object System.Collections.Generic.List[object] Get-Service | Where-Object { $_.StartType -like "Automatic" -and $_.Status -ne "Running" } | ForEach-Object { $NonRunningAutoServices.Add($_) } # Remove services from the list that have triggers or are set to delayed start, if ($NonRunningAutoServices.Count -gt 0) { $TriggerServices = Get-ChildItem -Path "Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\*\*" -ErrorAction SilentlyContinue | Where-Object { $_.Name -match "TriggerInfo" } $TriggerServices = $TriggerServices | Select-Object -ExpandProperty PSParentPath | Split-Path -Leaf foreach ($TriggerService in $TriggerServices) { $NonRunningAutoServices.Remove(($NonRunningAutoServices | Where-Object { $_.ServiceName -match $TriggerService })) | Out-Null } $DelayedStartServices = Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\*" | Where-Object { $_.DelayedAutoStart -eq 1 } $DelayedStartServices = $DelayedStartServices | Select-Object -ExpandProperty PSChildName foreach ($DelayedStartService in $DelayedStartServices) { $NonRunningAutoServices.Remove(($NonRunningAutoServices | Where-Object { $_.ServiceName -match $DelayedStartService })) | Out-Null } } # Remove explicitly ignored services from the list of non-running automatic services. if ($ServicesToIgnore.Count -gt 0 -and $NonRunningAutoServices.Count -gt 0) { foreach ($ServiceToIgnore in $ServicesToIgnore) { if ($NonRunningAutoServices.ServiceName -contains $ServiceToIgnore) { $NonRunningAutoServices.Remove(($NonRunningAutoServices | Where-Object { $_.ServiceName -match [Regex]::Escape($ServiceToIgnore) })) | Out-Null } } } # If there are still non-running automatic services left, display their names. # Otherwise, indicate no stopped automatic services were detected. if ($NonRunningAutoServices.Count -gt 0) { Write-Host "Matching Services found!" # Add Description to report. $ServicesReport = New-Object System.Collections.Generic.List[object] $NonRunningAutoServices | ForEach-Object { $Description = Get-CimInstance -ClassName Win32_Service -Filter "Name = '$($_.ServiceName)'" | Select-Object @{ Name = "Description" Expression = { $Characters = $_.Description | Measure-Object -Character | Select-Object -ExpandProperty Characters if ($Characters -gt 100) { "$(($_.Description).SubString(0,100))..." } else { $_.Description } } } $ServicesReport.Add( [PSCustomObject]@{ Name = $_.ServiceName Description = $Description | Select-Object -ExpandProperty Description } ) } # Output report to activity log. $ServicesReport | Sort-Object Name | Format-Table -Property Name,Description -AutoSize | Out-String | Write-Host } else { Write-Host "No stopped automatic services detected!" } # Exit the script if there are no services to start or if starting services is not requested. if (!$StartFoundServices -or !($NonRunningAutoServices.Count -gt 0)) { exit $ExitCode } # Attempt to start each non-running automatic service up to three times. # Log success or error messages accordingly. $NonRunningAutoServices | ForEach-Object { Write-Host "`nAttempting to start $($_.ServiceName)." $Attempt = 1 while ($Attempt -le 3) { Write-Host -Object "Attempt: $Attempt" try { $_ | Start-Service -ErrorAction Stop Write-Host -Object "Successfully started $($_.ServiceName)." $Attempt = 4 } catch { Write-Host -Object "[Error] $($_.Exception.Message)" if ($Attempt -eq 3) { $ExitCode = 1 } } $Attempt++ } } exit $ExitCode } end { }
Greifen Sie auf über 300 Skripte im NinjaOne Dojo zu.
Detailansicht
Schauen wir uns das Skript genauer an, um zu verstehen, wie es Schritt für Schritt funktioniert.
- Skriptinitialisierung und Parameter: Das Skript beginnt mit der Definition seines Zwecks und seiner Parameter. Er akzeptiert zwei optionale Parameter: -IgnoreServices, eine durch Komma getrennte Liste von Diensten, die ignoriert werden sollen, und -StartFoundServices, ein Schalter zum Starten der nicht laufenden Dienste, die die Kriterien erfüllen.
- Prüfung der Betriebszeit: Bevor das Skript fortfährt, prüft es die Betriebszeit des Systems, um sicherzustellen, dass es seit mindestens 15 Minuten in Betrieb ist. Dies verhindert Probleme im Zusammenhang mit Diensten, die nach einem Neustart möglicherweise nicht genügend Zeit hatten, um ordnungsgemäß zu starten.
- Prüfung der Berechtigungen: Das Skript stellt sicher, dass es mit Administratorrechten ausgeführt wird, weil das Stoppen und Starten von Diensten erhöhte Berechtigungen erfordert.
- Validierung von Diensten: Die zu ignorierenden Dienste werden validiert, um zu gewährleisten, dass sie keine ungültigen Zeichen enthalten und ihre Namen nicht übermäßig lang sind.
- Identifizierung nicht laufender Dienste: Das Skript sammelt eine Liste von Diensten, die automatisch gestartet werden sollen, aber derzeit nicht ausgeführt werden. Anschließend werden Dienste herausgefiltert, die auf ‘verzögerten Start’ eingestellt sind oder Auslösebedingungen haben.
- Berichterstattung und Maßnahmen: Wenn nicht laufende Dienste gefunden werden, meldet das Skript diese. Wenn der Schalter -StartFoundServices gesetzt ist, wird versucht, jeden dieser Dienste zu starten, wobei Erfolge und Fehler protokolliert werden.
Potenzielle Anwendungsfälle
Fallstudie:
Stellen Sie sich vor, eine IT-Expert:in verwaltet ein Netzwerk von Windows-Servern, auf denen verschiedene wichtige Anwendungen gehostet werden. Eines Tages melden die Benutzer:innen Probleme beim Zugriff auf eine wichtige Anwendung. Die IT-Expert:in führt dieses PowerShell-Skript aus, das feststellt, dass der Dienst der Anwendung, der auf automatischen Start eingestellt ist, nicht ausgeführt wird. Das Skript versucht, den Dienst neu zu starten, um das Problem schnell zu beheben und den normalen Betrieb wiederherzustellen.
Vergleiche
Dieses Skript bietet einen optimierten, automatisierten Ansatz im Vergleich zur manuellen Überprüfung jedes Dienstes über das MMC-Snap-In oder zur Verwendung anderer, weniger gezielter Skripte. Alternative Methoden, wie etwa die Verwendung vom Task Scheduler zur Überwachung von Diensten, können komplexer und schwieriger zu warten sein.
FAQs
F: Kann dieses Skript auch auf älteren Windows-Versionen verwendet werden?
A: Das Skript ist für Windows 10, Windows Server 2016 und neuer konzipiert. Die Kompatibilität mit älteren Versionen kann Anpassungen erfordern.
F: Was passiert, wenn ein Dienst nicht gestartet werden kann?
A: Das Skript versucht, jeden Dienst bis zu dreimal zu starten und protokolliert Fehler, wenn dies nicht gelingt.
F: Kann ich mehrere Dienste von der Prüfung ausschließen?
A: Ja, verwenden Sie den Parameter -IgnoreServices mit einer durch Komma getrennten Liste von Dienstnamen.
Folgen
Die Automatisierung der Überwachung und Verwaltung von Windows-Diensten erhöht die betriebliche Effizienz und verringert die Wahrscheinlichkeit von Ausfallzeiten. Die Gewährleistung, dass kritische Dienste immer laufen, kann die Zuverlässigkeit und Sicherheit des Systems verbessern.
Empfehlungen
- Regelmäßige Überwachung: Planen Sie die Ausführung des Skripts in regelmäßigen Abständen mithilfe vom Task Scheduler, um für eine kontinuierliche Überwachung zu sorgen.
- Protokollierung: Implementieren Sie zusätzliche Protokollierungs-Mechanismen, um einen Verlauf der vom Skript durchgeführten Aktionen zu erhalten.
- Prüfung: Testen Sie das Skript in einer Staging-Umgebung, bevor Sie es in der Produktion einsetzen.
Abschließende Überlegungen
Durch die Automatisierung der Verwaltung von Windows-Diensten können IT-Expert:innen für eine höhere Betriebszeit und Zuverlässigkeit ihrer Systeme sorgen. Für diejenigen, die ihren IT-Betrieb weiter rationalisieren möchten, bieten Tools wie NinjaOne umfassende Lösungen für die Überwachung, Verwaltung und Automatisierung verschiedener Aspekte der IT-Infrastruktur, die die Möglichkeiten dieses Skripts ergänzen.