Wie man einen Prozess als einen Service installieren kann

Unter verschiedene Umstände möchte man einen Prozess als Dienst installieren. In solch einem Fall wäre die erste Frage: ist der Prozess als Dienst gedacht?

· Warum ist das wichtig, und wie funktioniert der Service Control Manager?

Ein Dienst ist erst einmal nicht ein einfacher Prozess. Um einen Prozess als Dienst zu installieren, muss der Prozess als Dienst gedacht und geschrieben werden.

Dienste werden durch den SCM (Service Control Manager) manipuliert (gestartet, gestoppt, für automatischen Start konfiguriert, eingestellt um unter einem bestimmten Konto ausgeführt zu werden, etc) und die Kommunikation mit den Diensten erfolgt auch durch den SCM.

Beim Versuch, einen Dienst zu starten, startet der SCM den Prozess auf welchen der Dienst zeigt durch die CreateProcessAsUser Funktion, startet den Prozess aber in einem suspendierten Status. Als nächstes erstellt der SCM ein pipe, durch welches es mit dem Prozess, unter welchem der Dienst läuft, kommuniziert.

Der SCM lässt den Prozess dann weiterlaufen, so dass sich dieser an das pipe verbinden kann. Der SCM wartet auf die Verbindung für eine bestimmte Zeit (standard 30 Sekunden, der Wert wird aber in der Registry definiert und kann geändert werden: ServicesPipeTimeout ). Wenn sich der Prozess nach der bestimmten Zeit nicht an das pipe verbindet, beendet der SCM den gestarteten Prozess.

So dass ein Prozess als Dienst installiert wird, muss dieser die entsprechenden Funktionen ins code implementiert haben, um mit dem SCM kommunizieren zu können.

Ansonsten wird beim Versuch den Dienst zu Starten ein time-out Fehler berichtet:

- The service did not respond to the start or control request in a timely fashion.

· Wie wird der Prozess (der als Dienst gedacht wurde) als Dienst installiert?

Man kann:

a. instsrv.exe (Resource Kit) benutzen:

Pfad\instsrv MyService Path\test.exe

b. built-in sc.exe benutzen:

sc create MyService BinPath= „Path\test.exe” type= own

 

Dadurch wird der Dienst in services.msc hinzugefügt.

Gefilterter ProcMon output für sc create TestService BinPath= "C:\Windows\notepad.exe" type= own

7:36:44.6038125 PM services.exe 528 RegOpenKey HKLM\System\CurrentControlSet\services\TestService NAME NOT FOUND Desired Access: Read, Maximum Allowed

7:36:44.6038691 PM services.exe 528 RegCreateKey HKLM\System\CurrentControlSet\services\TestService SUCCESS Desired Access: Read/Write

7:36:44.6042087 PM services.exe 528 RegSetValue HKLM\System\CurrentControlSet\services\TestService\Type SUCCESS Type: REG_DWORD, Length: 4, Data: 16

7:36:44.6048827 PM services.exe 528 RegSetValue HKLM\System\CurrentControlSet\services\TestService\Start SUCCESS Type: REG_DWORD, Length: 4, Data: 3

7:36:44.6053339 PM services.exe 528 RegSetValue HKLM\System\CurrentControlSet\services\TestService\ErrorControl SUCCESS Type: REG_DWORD, Length: 4, Data: 1

7:36:44.6056072 PM services.exe 528 RegSetValue HKLM\System\CurrentControlSet\services\TestService\ImagePath SUCCESS Type: REG_EXPAND_SZ, Length: 46, Data: C:\Windows\notepad.exe

7:36:44.6063459 PM services.exe 528 RegSetValue HKLM\System\CurrentControlSet\services\TestService\ObjectName SUCCESS Type: REG_SZ, Length: 24, Data: LocalSystem

 

c. direkt in der Registry, manuell hinzufügen.

Wenn der Dienst in der Registry manuell hinzugefügt wird, muss das System neu gestartet werden, so dass die Änderungen erkannt werden.

Die empfohlene Methode ist aber den Dienst per sc.exe hinzuzufügen.

· Wie kann man einen Prozess als Dienst installieren, wenn er nicht als Dienst gedacht wurde?

a. Das nötige code hinzufügenJ

b. Ein wrapper benutzen:

1. Ein wrapper Prozess als Dienst installieren. Dadurch wird der wrapper Prozess gestartet.

srvany.exe (aus den Resource Kit Tools ) kann als wrapper benutzt werden:

sc create TestService BinPath= „Pfad\srvany.exe“ type=own

>sc query TestService

SERVICE_NAME: TestService

        TYPE : 10 WIN32_OWN_PROCESS

        STATE : 1 STOPPED

        WIN32_EXIT_CODE : 1077 (0x435)

        SERVICE_EXIT_CODE : 0 (0x0)

        CHECKPOINT : 0x0

        WAIT_HINT : 0x0

 

2. Jetzt haben wir den wrapper Prozess als Dienst installiert.

Dieser ist nicht nur so gedacht, als Dienst installiert werden zu können und mit dem SCM zu kommunizieren. Dieser kann aber auch eine Application als Parameter kriegen und diese dann starten.

Er ist ja ein wrapper und ermöglicht die Kommunikation SCM > non-service Prozess, non-service Prozess > SCM für Start-Stop Aktionen

Wie wir das machen:

… in Regedit (Start > Run > Regedit) den Dienst finden: HKLM\System\CurrentControlSet\Services\TestService

… rechte Maustaste auf TestService > New > Key è Parameters nennen

… rechte Maustaste auf Parameters > New > String Value è Application nennen

… doppel-Klick auf Application und den Wert eintragen: PfadZurApplikation (in meinem Beispiel ist es c:\Windows\notepad.exe gewesen)

            Der Dienst kann jetzt gestartet warden:

>net start TestService

                Und so sieht der notepad.exe als Dienst aus (child Prozess für den wrapper srvany.exe)

1

· Recovery Optionen

Da der notepad.exe als child Prozess für den srvany.exe gestartet wird, können wir die Recovery Optionen nicht für den notepad.exe Prozess benutzen.

Die Recovery Optionen werden für den srvany.exe Prozess gültig sein:

… wenn der notepad.exe abstürzt, werden keine Aktionen aus den Recovery Optionen ausgeführt; srvany.exe wird weiter laufen.

… wenn der srvany.exe abstürzt, wird der notepad.exe (unser Dienst) Prozess weiter laufen (aber nicht mehr unter der services.exe Struktur), die Recovery Aktion wird aber ausgeführt.

Wenn wir „Restart the service“ als Recovery Aktion einstellen, wird der Dienst neu gestartet und hiermit eine 2te notepad.exe Instanz auch.

2

Rot – Prozess der beendet wurde

Grün - neu gestartete Prozesse

Weitere Info zu dieses Thema:

KB137890 - How To Create a User-Defined Service

 

Viel Spaß beim Konfigurieren und Testen!J

 

Oni Sandru

Platforms Core Team