Anwendung aus Dienst heraus starten
Hi,
ich weiß, das Thema gab es hier schon öfter, aber eine Lösung habe ich bisher nicht gefunden (oder übersehen). Ich will aus einem Dienst heraus eine Anwendung starten. Mach ich zur Zeit mit ShellExecute was soweit auch funktioniert. Der Prozess wird zwar gestartet, aber das Window erscheint nicht. Und es scheint auch so, als dass der gestartete Prozess auch nichts macht (wobei ich das noch mal prüfen müsste). Der Prozess wird natürlich unter dem Konto gestartet, unter dem auch der Dienst läuft. Aber auch wenn ich das auf das Userkonto ändere ändert das nichts an dem Verhalten, außer, dass jetzt die Anwendung auch unter dem Userkonto gestartet wird, aber weiterhin ohne sichtbares Fenster. Gibt es eine Möglichkeit die Anwendung so zu starten (muß ja nicht mit Shellexecute sein), das das Fenster genauso erscheint, als hätte ich es manuell gestartet? |
AW: Anwendung aus Dienst heraus starten
Ist das nicht dieses Häkchen "Datenaustausch zwischen Dienst und Desktop zulassen"? in services.msc?
|
AW: Anwendung aus Dienst heraus starten
Zitat:
|
AW: Anwendung aus Dienst heraus starten
Den Haken gibt's auch nicht mehr....leider.
Bin grad mit einer Batchdatei am testen, aber so richtig klappt das auch nicht. Ich könnt mir natürlich ein kleines Programm in die TBNA legen, welches das dann sicherlich zuverlässig erledigt. Aber ich hatte gehofft noch eine andere (bessere) Lösung zu finden. |
AW: Anwendung aus Dienst heraus starten
Also ich weiß nicht, ob es jetzt wirklich ein Dienst sein muss, und ob er nun im Konto SYSTEM laufen soll oder im Benutzerkonto. Gehen tut das schon. Ich habe es bislang aber nur so gemacht dass eine Anwendung auf dem SYSTEM-Konto läuft und die Anwendung dann auf dem Desktop des grade lokal angemeldeten Benutzers aufmacht.
Sieht bei mir so aus:
Delphi-Quellcode:
und
interface
type /// <summary> /// Startet einen Prozess in der Session des grade angemeldeten Users /// </summary> /// <remarks> /// <para>Muss von einer Anwendung im Kontext von <c>SYSTEM</c> aufgerufen /// werden</para><para>Benötigt Windows Vista oder höher</para> /// <para>Ich habe keine Ahnung wie sich das bei RPD verhält</para> /// </remarks> TLocalProcessLauncher = class protected /// <remarks> /// Das zurückgegebene <c>THandle</c> muss, wenn es nicht mehr /// benötigt wird, mit <c>WinApi.Windows.CloseHandle(..)</c> /// geschlossen werden /// </remarks> /// <summary> /// Liefert das <i>Client Access Token</i> um mittels /// <c>CreateProcessAsUser(..)</c> einen Prozess im Kontext /// der lokal angemeldeten Session starten zu können /// </summary> /// <exception cref="EOSError" /> class function createSessionToken(): THandle; public /// <exception cref="EOSError" /> class procedure launchProcess( const absolutePath: String; const arguments: String = '' ); end platform;
Delphi-Quellcode:
Man sollte sich aber bewusst sein was das für ein gewaltiges Sicherheitsrisiko ist. Ich habe dafür auch keinen praktischen Anwendungsfall und das nur mal aus Spaß gemacht...
implementation
uses System.IOUtils, Winapi.Windows, System.SysUtils; class function TLocalProcessLauncher.createSessionToken(): THandle; const SE_DEBUG_NAME = 'SeDebugPrivilege'; desiredAccess: DWORD = TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY or TOKEN_DUPLICATE or TOKEN_ASSIGN_PRIMARY or TOKEN_ADJUST_SESSIONID or TOKEN_READ or TOKEN_WRITE; var sessionID: DWORD; serviceToken: THandle; userToken: THandle; tokenPriv: TTokenPrivileges; luid: TLargeInteger; //wtf? begin sessionID := WTSGetActiveConsoleSessionId(); Win32Check( OpenProcessToken( GetCurrentProcess(), desiredAccess, serviceToken ) ); try Win32Check( LookupPrivilegeValue(nil, SE_DEBUG_NAME, luid) ); tokenPriv.PrivilegeCount := 1; tokenPriv.Privileges[0].Luid := luid; tokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; Win32Check( DuplicateTokenEx( serviceToken, MAXIMUM_ALLOWED, nil, WinApi.Windows.SecurityIdentification, WinApi.Windows.TokenPrimary, userToken ) ); Win32Check( SetTokenInformation(userToken, TokenSessionId, @sessionID, SizeOf(sessionID)) ); finally CloseHandle(serviceToken); end; Result := userToken; end; class procedure TLocalProcessLauncher.launchProcess(const absolutePath, arguments: String); var token: THandle; args: PChar; startupInfo: TStartupInfo; processInfo: TProcessInformation; begin if arguments.IsEmpty() then args := nil else args := PChar(arguments); token := createSessionToken(); try startupInfo := Default(TStartupInfo); startupInfo.cb := SizeOf(TStartupInfo); startupInfo.lpDesktop := 'winsta0\Default'; Win32Check( CreateProcessAsUser( token, PChar(absolutePath), args, nil, nil, false, NORMAL_PRIORITY_CLASS or CREATE_NEW_CONSOLE, nil, nil, startupInfo, processInfo ) ); finally CloseHandle(token); end; end; |
AW: Anwendung aus Dienst heraus starten
Das kann mit ShellExecute nicht funktionieren. Dienste laufen in einer anderen Windowstation. Siehe hier: http://michael-puff.de/Programmierun...Stations.shtml
|
AW: Anwendung aus Dienst heraus starten
Aber wenn er sagt dass sein Service im Kontext des aktuellen Benutzers läuft? Dann unterscheidet er sich doch eigentlich gar nicht von einer normalen Anwendung die der Benutzer gestartet hätte, oder? Warum sollte ShellExecute dann nicht klappen?
Grade kurz ausprobiert, es klappt tatsächlich nicht. Aber warum? |
AW: Anwendung aus Dienst heraus starten
Ein Dienst läuft unter dem System Konto, welches in einer anderen WindowsStation läuft.
|
AW: Anwendung aus Dienst heraus starten
Das habe ich verstanden, aber ein Dienst kann doch ebenso gut in einem anderen Kõnto laufen, unter anderem das des grade angemeldeten Benutzers.
|
AW: Anwendung aus Dienst heraus starten
Dann ist es kein Dienst. Dann ist es ein Programm, was einfach beim Anmelden des Benutzers gestartet (Stichwort Autostart) wird und beim Abmelden wieder beendet. Ein Dienst hat ja gerade die Besonderheit, dass er unter dem System Konto läuft und so erweiterte Berechtigungen hat. Zum Beispiel um Updates installieren zu können.
Er könnte mit CreateProcessAsUser aus dem Dienst heraus ein Programm starten, was im Kontext des Benutzers läuft. Dazu braucht es aber dessen Anmeldedaten. |
AW: Anwendung aus Dienst heraus starten
Also, es muss ein Dienst (TService) sein.
Aber er kann unter einem beliebigen Benutzerkonto ausgeführt werden. Das sind die Vorgaben, an die ich mich halten muss (wenn's denn geht) Aber warum es wenn der Dienst unter einem anderen Benutzer läuft kein Dienst mehr sein soll ist mir nicht klar. Ich kann doch in der Dienst-Konsole für einen Dienst explizit ein Benutzerkonto auswählen (Es gibt ja auch das Recht für Benutzerkonto "Als Dienst anmelden"). Das hat doch dann auch nichts mit Autostart zu tun. Sprich: ich kann einen Dienst unter meinem Benutzerkonto starten, der auch weiter läuft wenn ich mich abmelde. Das Programm kann ja auch gestartet werden, laut Taskmanager und es läuft auch unter den gleichen Benutzerkonto laut Taskmanager. Es scheint nur das Problem zu sein, dass das MainWindow sich nicht auf dem Desktop erzeugt. Anmeldedaten brauch ich dafür eigentlich auch nicht, da diese ja schon in der Dienste-Konsole hinterlegt worden sind. |
AW: Anwendung aus Dienst heraus starten
Erklär doch mal, was eigentlich der "Dienst" machen soll? Und warum es ein Dienst sein muss.
|
AW: Anwendung aus Dienst heraus starten
Weil er per TCP Kommandos empfängt, und über die Kommandos dann andere Dienste starten bzw. Neustarten und auch Programme auf dem Desktop des angemeldeten Benutzers.
Programme natürlich nur, wenn ein Benutzer angemeldet ist, aber Dienste auf jeden Fall, auch wenn z.Zt. Kein Benutzer angemeldet ist. Wenn's nicht geht, dann schreib ich mir halt noch was, das beim Logon des Users als Programm in der TBNA liegt und diese Aufgabe für Programme übernimmt. Ich dachte halt, das es eigentlich gehen sollte. |
AW: Anwendung aus Dienst heraus starten
Das hier sollte eigentlich alles notwendige erklären:
http://blogs.msdn.com/b/winsdk/archi...and-later.aspx |
AW: Anwendung aus Dienst heraus starten
Zitat:
Also du hast einen Dienst der Anweisungen über das Netzwerk bekommt und die bestehen unter anderen darin andere Dienste zu starten oder für den angemeldeten Benutzer Programme? OK, andere Dienste Starten sollte kein Problem sein. Für den angemeldeten Benutzer schon. Denn für welchen angemeldeten Benutzer? Wenn ich aus dem Startmenü den Menüpunkt "Benutzer wechseln" auswähle, dann sind schon mal zwei oder mehr Benutzer angemeldet. Dann gibt es noch Terminal Sessions. Um es kurz zu machen, es gibt nicht DEN angemeldeten Benutzer. |
AW: Anwendung aus Dienst heraus starten
Ja, ihr habt recht. Nach dem Artikel von Stevie ist mir das auch klar, warum. Und die vielen Wiederholungen von den Wörten "Never, no, don't do this, usw" sagen ja auch aus, dass man es wohl tunlichst lassen sollte (aber immerhin auch das es mal theoretisch gehen könne ;) )
Und selbst wenn es doch hinbekommt ist ja zum einen am Sicherheitssystem komplett vorbei und zum anderen würde es bei kommenden Win-Generationen sicherlich wieder Probleme aufwerfen. Deshalb werde ich mein ursprüngliches Vorhaben verwerfen. Das der Dienst per TCP-Kommando andere Dienste startet funktioniert schon wunderbar. Für das Starten der Programm werde ich den Dienst als Programm kompilieren, der über Autostart in der TBNA schlummert und eben das gleiche für die Programme übernimmt. Ich denke das ist auch eine ganz gute Lösung. Zitat:
Ich fand ihn sehr informativ, und hab auch den Rest gelesen. |
AW: Anwendung aus Dienst heraus starten
Es gibt sehr wohl Anwendungen in welchen es Sinn macht aus einem Dienst welcher unter dem Systemkonto läuft Anwendungen im User Kontext zu starten. Das machen unter anderem Remote Access Tools wie Teamviewer. Auch für benutzerspezifische Updates wird das gebraucht. Und: wo soll genau das Sicherheitsproblem in einem selbst erstellten Dienst sein?
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz