Behandelte Themen unter "Dienste"
0.
einige Basisbeispiele
Beispiel 1a: Alle installierten Dienste anzeigen (get-service/ .Net)
Beispiel 1b: Alle installierten Dienste anzeigen (WMIKlasse: win32_service)
Beispiel 2: Monitoring und automatischer Neustart von Diensten
2.
2.1
0 Einleitung
Dienste lokal und remote auf einem oder mehreren Rechnern zu verwalten, zu überwachen, zu starten, zu stoppen und zu erforschen ist der Gegenstand dieses Kapitels.
Zum Skripten stehen einige Ansätze zur Verfügung, die je nach Aufgabenstellung mal mehr mal weniger geeignet sind.
Beispiel | Vorteile | Nachteile | CodeBeispiel | |
Powershell cmdlets | get-help service Get-Service (gsv) | Intuitives PowershellSkripting OnlineHilfe | Nicht alle Diensteigenschaften verfügbar
| gsv -computername PC1 |
.Net Klassen | Vorteile wie cmdlets Methoden und Eigenschaften liegen in der MSDN | keine intuitive Syntax | $a=[serviceprocess.servicecontroller] | |
WMI | liefert die meisten Eigenschaften eines Dienstes Besonders bei Remoteabfragen durch | Syntax etwas komplexer als cmdlets | $qry = "select * from win32_service" | |
CommandlineTools | weit verbreitetes CMD-Tool | läuft nicht in Powershell | SC | |
1 einige Basisbeispiele
Die cmdlets zur Verwaltung von Diensten sind recht einfach und verständlich. Daher zeige ich in diesem Kapitel nur einige Beispiele, ohne allzuviele Worte zu verlieren.
Beispiel 1a: Alle installierten Dienste anzeigen (get-service/ .Net)
get-service -computername pc1 | sort-object -descending
#gsv -computername pc1 | sort -descending #Alias gsv und sort
# [serviceprocess.servicecontroller]::getservices("pc1") | sort status #.Net
#Ausgabe gekürzt
Status Name DisplayName
------ ---- -----------
Running RasMan RAS-Verbindungsverwaltung
Running RemotePersonali... Remote Personalisation
...
Stopped Browser Computerbrowser
Stopped MSIServer Windows Installer
Beispiel 1b: Alle installierten Dienste anzeigen (WMIKlasse: win32_service)
$qry = "select * from win32_service"
get-wmiobject -query $qry -computername pc1 | sort-object state | format-table state,name,caption -autosize
# gwmi -query $qry -computername pc1 | sort state | ft state,name,caption -auto #mit Aliassen
#Ausgabe gekürzt
state name caption
----- ---- -------
Running RasMan RAS-Verbindungsverwaltung
Running RemotePersonalisation Remote Personalisation
....
Stopped SysmonLog Leistungsdatenprotokolle und Warnungen
Stopped ClipSrv Ablagemappe
Wie man sieht, sind die Eigenschaftsnamen der .Net-Klasse und der Win32-Klasse nicht gleich.
Beispiel 2: Monitoring und automatischer Neustart von Diensten
$servicename="LENOVO.CAMMUTE" #mein Beispiel Dienst
$timespan = New-Object System.TimeSpan(0,2,0) # gibt in Stunden,Minuten,Sekunden an, wie oft der Monitor läuft
$scope = New-Object System.Management.ManagementScope("\\.\root\cimV2") #. steht für den lokalen Rechner
$query = New-Object System.Management.WQLEventQuery `
("__InstanceModificationEvent",$timespan, "TargetInstance ISA 'Win32_service'" )
$watcher = New-Object System.Management.ManagementEventWatcher($scope,$query)
do
{
$b = $watcher.WaitForNextEvent()
$b.TargetInstance.Name
$b.TargetInstance.caption # Eigenschaftenn der WMI-Klasse: win32_service
if ($(get-service -name $servicename).status -eq "Stopped") {
start-service -name $servicename -force
# emailfunktionalität + Protokollierung muß noch hinzugefügt werden
}
}
while ($a -ne 1)
Dieses Skript bietet eine einfache und günstige Möglichkeit ein paar Dienste zu überwachen.
Beschreibung:
Das Skript läuft nach dem Start endlos und monitored alle 2 Minuten, ob die Dienste modifiziert wurden. Falls ja und der Dienst "LENOVO.CAMMUTE" auf "Stopped" steht, wird dieser Dienst neu gestartet.
Über $timespan und $servicename kann man diese beiden Parameter natürlich anpassen.
Erklärung: Das Herzstück des Skripts ist die Überwachung der Win32_service - Klasse mit
2 einen neuen Dienst erstellen
Mit new-service ist ein leichtes einen neuen Dienst zu installieren, wenn man eine passende exe-Datei zu Verfügung hat.
Beispiel 1: Installation eines Dienstes
new-service -name Telnet2 -binarypath C:\WINDOWS\system32\tlntsvr.exe -Displayname telnet2 -description "das ist ein Testsservice"
#Ausgabe
Status Name DisplayName
------ ---- -----------
Stopped telnet2 telnet2
Den binarypath des Telnetservices habe ich mir in der services.msc imTelnetservice besorgt und hier einfach zu Demonstrationszwecken des new-service verwendet.
Die eigentliche Herausforderung liegt in der Programmierung einer geeigneten exe. Für Visualbasic habe ich dazu diese Anleitung gefunden
Mit dem Assistenten in VisualStudio ist die Aufgabe eine Exe als Dienst zu programmieren auch wieder nicht allzu schwierig. Im nächsten Kapitel gibts ein konkretes Beispiel dazu.
2.1 Einen Dienst in VisualBasic programmieren
In diesem Kapitel zeige ich, wie man einen Dienst unter VisualStudio/ VisualBasic programmieren kann.
Wir programmieren einen Dienst, der beim Start sämtliche Treiber samt Treiberversion ins Windows Eventlog schreibt. Wenn plötzliche Treiberprobleme auftauchen, sind diese Events eine guter Einstiegspunkt zum Troubleshooting des Systems.
Die folgenden Screenshots habe ich unter VisulaStudio 2010 erstellt. Mit VisualStudio 2008 funktioniert eine Diensterstellung aber sehr ähnlich.
Der VBCode (2010) sieht so aus (Der Projekttyp lautet "Windows Dienst" !)
'Unter Verweise bitte einen Verweis auf System.Management einrichten
Imports System.Management
Module Module1
'
Sub drivers()
Dim objQuery As New ObjectQuery("SELECT * FROM Win32_systemdriver")
Dim searcher As New ManagementObjectSearcher(objQuery)
Dim myLog As New EventLog()
myLog.Source = "Drivers"
Dim eventoutput As String = "by blub@mcseboard.de" & vbCrLf
eventoutput += "Alle mit win32_systemdriver erfassten Treiber am " & Now & ":" & vbCrLf & vbCrLf
For Each member As ManagementObject In searcher.Get
Dim DName As String = member("Displayname")
Dim DPath As String = member("pathname")
Dim Dversion As String = ""
Dim DDescription As String = ""
Dim DCompanyName As String = ""
Dim tmp1 As String = getDriverinfo(DPath, Dversion, DDescription, DCompanyName)
Try
Dim output As String = DName & " - " & Dversion & vbCrLf '& ";" & DCompanyName & ";" & DPath
eventoutput += output
Catch
End Try
Next
Write2Log(eventoutput, myLog)
End Sub
Function getDriverinfo(ByVal funDpath As String, ByRef funDriverversion As String, _
ByRef funFileDescription As String, ByRef funCompanyName As String)
getDriverinfo = ""
Try
Dim funFileVersionInfo As FileVersionInfo = FileVersionInfo.GetVersionInfo(funDpath)
funFileDescription = funFileVersionInfo.FileDescription
funDriverversion = funFileVersionInfo.FileVersion
funCompanyName = funFileVersionInfo.CompanyName
Catch
End Try
End Function
Public Sub Write2Log(ByVal SubOutput As String, ByRef subMyLog As EventLog)
subMyLog.WriteEntry(SubOutput, EventLogEntryType.Information, 4711)
End Sub
End Module
Public Class mydrivers02
Protected Overrides Sub OnStart(ByVal args() As String)
' Code zum Starten des Dienstes hier einfügen. Diese Methode sollte Vorgänge
' ausführen, damit der Dienst gestartet werden kann.
drivers()
End Sub
Protected Overrides Sub OnStop()
' Hier Code zum Ausführen erforderlicher Löschvorgänge zum Beenden des Dienstes einfügen.
EventLog.WriteEntry("getDrivers Stopped at " & Now)
End Sub
End Class
Die exe zum Download gibts hier:
und mit diesem Powershellskript wird der zugehörige Dienst angelegt
$path="C:\Programme\Drivers2Eventlog\drivers2Eventlog.exe"
$name="Drivers2Log"
new-service -name $name -binarypath $path -Displayname $name -description "erzeugt im Anwendungslog ein Event mit allen Treibern"
#Ausgabe
Status Name DisplayName
------ ---- -----------
Stopped Drivers2Log Drivers2Log
In Kapitel