Windows-Dienst: Kann ich das aktuelle Arbeitsverzeichnis konfigurieren?

11

Standardmäßig werden Windows-Dienste (normalerweise C:\WINDOWS\system32) im Verzeichnis sytem32 gestartet .

Gibt es eine Möglichkeit, ein anderes Arbeitsverzeichnis einzurichten? Ich denke an einige Registrierungsparameter darunter HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SomeService.

Also - kann das gemacht werden?

Tomalak
quelle
3
@Tomalak: Ist es ein Dienst, den Sie geschrieben haben? Sie können dies über Code tun, aber ich glaube nicht, dass es einen Weg durch die Serviceeinstellungen gibt.
MattB
Nein, es ist kein Dienst, den ich geschrieben habe. Ich hatte gehofft, hier eine wenig bekannte Registrierungseinstellung zu haben.
Tomalak
Was ist der Zweck davon?
Benutzer35115
@ user35115: Nun, um ehrlich zu sein ... Als ich ein nicht verwandtes Problem mit procmon aufspürte, bemerkte ich, dass ein bestimmter I / O-lastiger Dienst (ein Volltextindexer) ständig an den falschen Stellen nach seinen eigenen Dateien sucht (ziemlich dumm). Es startet bei system32, versucht ein paar weitere Speicherorte und schließlich ein eigenes Verzeichnis. Ich dachte mir, wenn es sofort in einem eigenen Verzeichnis laufen würde, würde es weniger unnötige Dateiprüfungen durchführen. Nicht, dass es derzeit nicht funktionieren würde , aber ich habe mich gefragt, ob es Raum für Verbesserungen gibt.
Tomalak
1
@ user35115, Um zu vermeiden, dass die Konfigurationseinstellungen einer bestimmten App (z. B. Apache usw.), die sich alle auf das Arbeitsverzeichnis beziehen, massiv geändert werden müssen .
Pacerier

Antworten:

5

Sie können die DLL-Injection verwenden, um aufzurufen, SetCurrentDirectorynachdem der Prozess bereits gestartet wurde. Dies würde erfordern, dass Sie eine Injektoranwendung sowie die zu injizierende DLL erstellen. Es gibt einige Tutorials. wahrscheinlich sind die zwei besten, die ich gefunden habe:

Sie benötigen eine angemessene Menge an C ++ - Programmierhintergrund (und eine funktionierende Build-Umgebung), um dies zu bewältigen.

Dies setzt jedoch voraus, dass der Dienst das aktuelle Verzeichnis betrachtet. Eine andere Möglichkeit ist, dass es verwendet %path%. Sie sagen, dass es "an beginnt system32, ein paar weitere Orte ausprobiert und schließlich ein eigenes Verzeichnis", also scheint mir dies wahrscheinlicher.

Vergleichen Sie die Verzeichnisse, die Sie sehen, procmonmit Ihren %path%. Wenn sie identisch sind, sollten Sie entweder das SYSTEM %path%oder das %path%des Benutzers ändern, der den Dienst ausführt, sodass das Verzeichnis, in dem er durchsucht werden soll, an erster Stelle steht.

Ich glaube jedoch, dass Fred Recht hat - es ist unwahrscheinlich, dass Sie dadurch einen signifikanten Leistungsvorteil sehen, es sei denn, dies geschieht sehr häufig. Einfache Dateiöffnungsvorgänge sind nicht besonders teuer, insbesondere wenn es sich um einen lokalen Pfad handelt und die Datei nicht vorhanden ist.

Fission
quelle
Die Umgebungsvariable system PATH war das erste, was mir in den Sinn kam. Das Einfügen des Dienstpfads am Anfang der PATH-Variablen wirkt sich jedoch negativ auf die Leistung nahezu jeder anderen Anwendung aus, sodass ich dies nicht empfehlen würde.
Marnix van Valen
Ich habe keine harten Zahlen, um dies zu belegen, aber meine Intuition sagt mir, dass durch das Ändern des Pfads kein praktischer Leistungsgewinn oder -verlust entstehen würde. Dies ist ein ziemlich häufiges Szenario. Niemand beschuldigt beispielsweise die Windows Support Tools oder SQL Server, die Systemleistung negativ beeinflusst zu haben, wenn der Pfad während der Installation geändert wird. Dies ist nicht das erste Mal, dass ich jemanden sehe, der sich procmon ansieht und "omg, sieh dir all diese Dateizugriffe an!" Sagt, ohne zu bemerken, dass dies für die meisten Anwendungen typisch ist.
Spaltung
+1 für Kreativität. :-) Ich verstehe voll und ganz, dass diese Dateioperationen die Leistung nicht messbar beeinflussen, daher werde ich mir nicht die Mühe machen, eine DLL-Injektionslösung zu schreiben. Das Ändern %PATH%des Benutzerkontos, unter dem der Dienst ausgeführt wird, ist jedoch eine gute Idee.
Tomalak
1
Das Erstellen eines speziellen Benutzers, um nur diesen Dienst auszuführen, und das Ändern von% PATH% für diesen Benutzer ist ein sehr guter Weg. +1
Sunny
@fission: Ja, das heißt, ich akzeptiere deine Antwort. ;) Es ist nicht das, was ich mir erhofft hatte, aber es ist so nah wie es nur geht, denke ich.
Tomalak
1

Wie bei MattB kenne ich keine Möglichkeit, das Arbeitsverzeichnis des Dienstes ohne Zugriff auf den Quellcode zu ändern. In diesem speziellen Szenario ist es wahrscheinlich, dass die zusätzlichen Verzeichnisprüfungen nicht so viel unnötige Festplattenaktivität im Verhältnis zu der für die Volltextindizierung erforderlichen E / A-Menge verursachen. Selbst wenn Sie sie wegoptimieren könnten, ist der Volltextindex von Natur aus festplattenintensiv.

Fred
quelle
1

Fügen Sie dem Parameterschlüssel einen Zeichenfolgenwert "AppDirectory" hinzu und legen Sie den Wert auf das gewünschte Arbeitsverzeichnis fest.

Kennzeichen
quelle
Hm. Gerade getestet, scheint nicht zu funktionieren (unter Windows 7 wird der Datentyp REG_EXPAND_SZ verwendet). Können Sie bitte erneut bestätigen, dass dies tatsächlich für Sie funktioniert?
Tomalak
Dies funktioniert bei der Verwendung srvany. Ich bin mir nicht sicher über normale Dienste.
Konstantin Spirin
1

Tun Sie dies innerhalb der Service-Hauptfunktion:

  • Rufen Sie an GetModuleFilename. Der Dateiname des Moduls (exe) einschließlich des Pfads wird im Formular abgerufen C:\path\to\exe\your_service.exe.
  • Verwenden Sie Zeichenfolgenmanipulationen (möglicherweise mithilfe der std::stringFunktion find_last_of()), um den letzten Backslash zu finden. Entfernen Sie von dort aus den String, um den Pfad zu Ihrem Modul und damit das Verzeichnis Ihrer Exe zu erhalten.
  • Rufen Sie die Funktion an SetCurrentDirectoryund voila!
Aufrichtigkeit
quelle
1
Vergessen Sie nicht, im Funktionsaufruf GetModuleFilename null an den Parameter HMODULE zu übergeben :)
Aufrecht