![]() |
Re: Programm von Dienst starten lassen (Jetzt aber wirklich
Zitat:
Zitat:
|
Re: Programm von Dienst starten lassen (Jetzt aber wirklich
Zitat:
Zitat:
Prinzipiell würde ich das ja so machen:
Delphi-Quellcode:
Aber WTSGetActiveConsoleSessionId liefert mir ja nur die SessionID von SYSTEM, bringt also nichts. Wie muss der Code statt dessen lauten, damit ich die Umgebung dann bei CreateProcess mit übergeben kann?
function GetEnvironment(): LPVOID;
var LToken: THandle; LDupToken: THandle; LSessionID: DWORD; begin Result := nil; LSessionID := WTSGetActiveConsoleSessionId; //<- da muss wohl was anderes hin... WTSQueryUserToken(LSessionID, @LToken); DuplicateTokenEx(LToken, TOKEN_ASSIGN_PRIMARY or TOKEN_ALL_ACCESS, nil, SecurityIdentification, TokenPrimary, LDupToken); if (not CreateEnvironmentBlock(Result, LDupToken, True)) then Result := nil; end; function RunProcess(FileName: string): Longword; var StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; begin FillChar(StartupInfo, SizeOf(StartupInfo), #0); StartupInfo.cb := SizeOf(StartupInfo); StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK; StartupInfo.wShowWindow := SW_SHOW; if not CreateProcess(nil, @Filename[1], nil, nil, False, NORMAL_PRIORITY_CLASS or CREATE_NEW_PROCESS_GROUP, //<- stimmen die Flags so? GetEnvironment, //<- hier die Umgebung des normalen Benutzers übergeben nil, StartupInfo, ProcessInfo) then Result := WAIT_FAILED; end; Huch, doch schon so spät. Du siehst, mir lässt das keine Ruhe. Ich gehe jetzt erstmal schlafen... |
Re: Programm von Dienst starten lassen (Jetzt aber wirklich
WTSQueryUserToken returns a user's primary token so you don't need to duplicate it. Just past the tokenhandle to CreateProcessAsUser and be sure to pass nil for the desktop param of the startupinfo structure. Something like this:
Delphi-Quellcode:
Notes: WTSQueryUserToken needs Windows XP/2003 or higher, if you need windows 2000 compatibility check Jwscl as it contains a WTSQueryUserTokenEx function that also works on Windows 2000.
// Obtain the primary user token
WTSQueryUserToken(SessionId, hToken); if hToken <> 0 then begin // Fill buffer with zeroes ZeroMemory(@si, SizeOf(si)); si.cb := SizeOf(si); si.lpDesktop := nil; if CreateProcessAsUser(hToken, nil, Cmd, nil, nil, False, 0, nil, nil, si, pi) then ... |
Re: Programm von Dienst starten lassen (Jetzt aber wirklich
Willst du das wirklich alles nur mit der WinAPI machen? Das geht natürlich. Plane aber mal noch 3-4Wochen Zusatzaufwand dafür ein. Ich selbst würde da nur noch die JWSCL benutzen.
|
Re: Programm von Dienst starten lassen (Jetzt aber wirklich
Zitat:
Delphi-Quellcode:
function GetEnvironment(): LPVOID;
var SessionID : DWORD; hToken : THandle; begin Result := nil; WTSQueryUserToken(SessionID, hToken); if (not CreateEnvironmentBlock(Result, hToken, True)) then Result := nil; end; Zitat:
Zitat:
|
Re: Programm von Dienst starten lassen (Jetzt aber wirklich
Ok, nach einer vollständigen und peniblen Neuinstallation funktioniert Jwa und Jwscl jetzt wohl. Scheint was durcheinander gekommen zu sein mit der alten und der aktuellen Version. Nun gut, das geht ja jetzt schon mal. Dann versuche ich jetzt mal da drauf aufzubauen.
Das habe ich jetzt zusammengebasteln:
Delphi-Quellcode:
1. Ich verwende CreateProcess und nicht CreateProcessAsUser, weil ich ja gar nicht brauche, dass das Programm als anderer Benutzer ausgeführt wird. Ist das dann so OK?
var
UserToken: TJwSecurityToken; ConsoleUser : TJwSecurityId; StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; UserEnvironment : LPVOID; begin UserToken := TJwSecurityToken.CreateWTSQueryUserTokenEx(nil, WtsGetActiveConsoleSessionID); try ZeroMemory(@StartupInfo, SizeOf(StartupInfo)); StartupInfo.cb := SizeOf(StartupInfo); StartupInfo.lpDesktop := nil; StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK; StartupInfo.wShowWindow := SW_SHOW; CreateEnvironmentBlock(UserEnvironment, UserToken.TokenHandle, True); //<- so richtig? CreateProcess(nil, PChar('c:\test.exe'), nil, nil, False, NORMAL_PRIORITY_CLASS or CREATE_NEW_PROCESS_GROUP, UserEnvironment, //<- EnvironmentBlock nil, StartupInfo, ProcessInfo); finally FreeAndNil(UserToken); end; end; 2. Die Umgebung (UserEnvironment) wird nicht richtig verarbeitet. Wenn ich nil statt UserEnvironment übergebe, dann startet das Programm als SYSTEM hat aber auch dessen Umgebungsvariablen. Wenn ich aber versuche, den EnvironmentBlock zu erstellen (wie im Code dargestellt), dann startet das Programm gar nicht mehr. Wo liegt der Fehler? Bzw. wie geht das richtig? 3. Selbst wenn das dann starten würde, bin ich immer noch der Meinung, dass bei Verwendung von WtsGetActiveConsoleSessionID ich die Umgebung von SYSTEM erhalte und nicht vom User. Wie dann? edit: Hm, habe das jetzt mit UserToken.GetTokenUserName überprüft und es ist der Benutzername. Sollte dann also wohl doch so funktionieren... |
Re: Programm von Dienst starten lassen (Jetzt aber wirklich
Zitat:
Zitat:
![]() |
Re: Programm von Dienst starten lassen (Jetzt aber wirklich
Du hast wohl alles schon mal gemacht, oder? :)
Habe ein wenig mit Deiner Funktion herumexperimentiert. Hier meine Ergebnisse: Wenn ich die Funktion genau so übernehme, dann wird die Umgebung von "Default User" genommen. Zum Testen schaue ich immer über SHGetSpecialFolderLocation nach, welcher Bentzerordner aus dem Programm heraus angezeigt wird. Nehme ich bei CreateEnvironmentBlock als zweiten Parameter 0, erhalte ich C:\Dokumente und Einstellungen\Default User\Anwendungsdaten Mit der nachfolgenden Änderung kommt das gewünschte C:\Dokumente und Einstellungen\MyUser\Anwendungsdaten Ich denke
Delphi-Quellcode:
sollte deshalb geändert werden.
CreateEnvironmentBlock(@pEnv, 0, true);
Das hier funktioniert als Ersatz:
Delphi-Quellcode:
Damit läuft das Programm als SYSTEM Anwendung aber mit der Umgebung des aktuellen Benutzers. :D
//UserToken := TJwSecurityToken.CreateWTSQueryUserTokenEx(nil, WtsGetActiveConsoleSessionID); //nur ab XP :(
UserToken := TJwSecurityToken.CreateCompatibilityQueryUserToken(MAXIMUM_ALLOWED, 'explorer.exe'); //auch für 2000! :) JwaWindows.CreateEnvironmentBlock(@pEnv, UserToken.TokenHandle, true); Bleibt noch eine Frage: Für Vista lässt sich da nichts mehr anpassen, oder? Da wird das Programm nämlich auf dem speziellen Desktop gestartet und entsprechend nicht normal angezeigt. Ja, ich weiß, das ist eine gewollte sicherheitsbedingte Änderung gewesen, aber vielleicht lässt sich da ja trotzdem noch was machen? |
Re: Programm von Dienst starten lassen (Jetzt aber wirklich
CreateWTSQueryUserTokenEx funktioniert nur unter Windows 2000. Unter XP kann es funkzen, muss aber nicht. Unter Vista funktioniert es nicht!
Damit dieser Desktopwechsel unter Vista nicht auftritt, musst man die TokenSessionID (Property) auf die jeweilige ID des Users setzen und dann damit das Programm starten.
Delphi-Quellcode:
var T,t2 : TJwSecurityToken;
S : TStartupInfo; P : TProcessInformation; begin T := TJwSecurityToken.CreateTokenEffective(MAXIMUM_ALLOWED); T2 := TJwSecurityToken.CreateDuplicateExistingToken(T.TokenHandle, MAXIMUM_ALLOWED); // T2.TokenSessionId := 2; ZeroMemory(@S, Sizeof(S)); S.cb := sizeof(S); CreateProcessAsUser(T2.TokenHandle,'C:\Windows\system32\cmd.exe',nil,nil,nil,false, 0, nil, nil, S,P); ... |
Re: Programm von Dienst starten lassen (Jetzt aber wirklich
Zitat:
Aber letztlich tut
Delphi-Quellcode:
ja vollkommen das, was es soll. Nachteile sehe ich keine.
UserToken := TJwSecurityToken.CreateCompatibilityQueryUserToken(MAXIMUM_ALLOWED, 'explorer.exe');
Dein Vista-Beispiel verstehe ich allerdings nicht. Ich schreibe doch da nicht wirklich eine 2 als TokenSessionId hinein? Jedenfalls funktioniert das Codeschnippsel bei mir auch nicht. Ich vermute, es liegt an der 2, weiß aber nicht, was ich da sonst übergeben soll. Klärst Du mich da bitte auf? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:22 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz