![]() |
Programm vom Dienst starten mit mehr Rechten???
Hallo Zusammen,
ich habe eine Anwendung, die als Dienst unter dem System-Account unter Windows läuft. Je nach Anforderung (wird von einem Webservice getriggert) soll der Dienst ein Programm deinstallieren. Da leider nicht jede Software direkt über msi-installiert wird, muss auch ggf. bei einer Deinstallation eine Benutzerinteraktion erfolgen. Hier besteht das Problem, dass der angemeldete User nicht unbedingt administrative Rechte besitzt. So habe ich mir gedacht, dass es möglich sein musste, das ich (als Dienst) eine Prozess für den angemeldeten Benutzer starte, und dass dieser Prozess administrative Rechte hat. Auf meine Suche nach einer Lösung bin ich auf folgendes gestoßen. ![]() Dieses ist aber nicht möglich, da bei uns die jwscl nicht verwendet werden soll. Aus diesem Grund suche ich nach einer Lösung mit Delphi-Boardmitteln. Die Verwendung der jwa ist aber möglich.
Delphi-Quellcode:
Nun meine simple Frage:
unit Unit2;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm2 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private function CreateProcess4LoggedOnUser(const cmd: String): Cardinal; procedure WriteLog(const aMessage: String); { Private-Deklarationen } public { Public-Deklarationen } end; var Form2: TForm2; implementation {$R *.dfm} uses TlHelp32, jwaWinBase, jwaUserEnv; procedure TForm2.Button1Click(Sender: TObject); begin CreateProcess4LoggedOnUser('C:\Programme\CCleaner\uninst.exe'); end; function TForm2.CreateProcess4LoggedOnUser(const cmd: String): Cardinal; var hToken : THandle; newToken : THandle; blub : Cardinal; aSessionId : Cardinal; aStartup : Windows.TStartupInfo; aPI : Windows.TProcessInformation; MyEnv : Pointer; bla : DWORD; begin Memo1.Lines.Clear; result := 0; if Windows.OpenProcessToken(GetCurrentProcess, TOKEN_ALL_ACCESS, hToken) then begin WriteLog('OpenProcessToken Ok'); if Windows.ImpersonateLoggedOnUser(hToken) then begin WriteLog('ImpersonateLoggedOnUser Ok'); if Windows.DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, nil, SecurityImpersonation, TOKENPRIMARY, newToken) then begin WriteLog('DuplicateTokenEx Ok'); aSessionId := jwaWinBase.WTSGetActiveConsoleSessionId; bla := DWORD(aSessionId); if Windows.SetTokenInformation(newToken, Windows.TokenSessionId, @bla, SizeOf(DWORD)) then //Hier wird ein Fehler ausgelöst: (Error-Code 1314): Dem Client fehlt ein erforderliches Recht begin WriteLog('SetTokenInformation Ok'); FillChar(aStartup,SizeOf(TStartupInfo),#0); FillChar(aPI,SizeOf(TProcessInformation),#0); aStartup.cb := SizeOf(TStartupInfo); aStartup.lpDesktop := 'WinSta0\Default'; MyEnv := nil; // Umgebungsvariablen werden vom Benutzer ermittelt. if jwaUserEnv.CreateEnvironmentBlock(@MyEnv, newToken, false) then begin WriteLog('CreateEnvironmentBlock Ok'); if Windows.CreateProcessAsUser(newToken, pChar(cmd), nil, nil, nil, true, NORMAL_PRIORITY_CLASS or CREATE_NEW_CONSOLE or CREATE_UNICODE_ENVIRONMENT, MyEnv, nil, aStartup ,aPI) then begin WriteLog('CreateProcessAsUser Ok'); CloseHandle(aPI.hProcess); CloseHandle(aPI.hThread); end else begin result := GetLastError; WriteLog('7: '+Sysutils.SysErrorMessage(result)); end; jwaUserEnv.DestroyEnvironmentBlock(MyEnv); end else begin blub := Windows.GetLastError; WriteLog('CreateEnvironmentBlock('+IntToStr(blub)+'): ' + Sysutils.SysErrorMessage(blub)); end; end else begin blub := Windows.GetLastError; WriteLog('SetTokenInformation('+IntToStr(blub)+'): ' + Sysutils.SysErrorMessage(blub)); end; end else WriteLog('DuplicateTokenEx: ' + Sysutils.SysErrorMessage(Windows.GetLastError)); end else WriteLog('ImpersonateLoggedOnUser: ' + Sysutils.SysErrorMessage(Windows.GetLastError)); end else WriteLog('OpenProcessToken: ' + Sysutils.SysErrorMessage(Windows.GetLastError)); end; procedure TForm2.WriteLog(const aMessage: String); begin Memo1.Lines.Add(aMessage); end; end. Was mach ich falsch |
AW: Programm vom Dienst starten mit mehr Rechten???
Hallo Zusammen,
ich hab den oben gezeigten Code als Programm und nicht als Dienst ausgeführt. Wenn man dieses als Dienst ausführt, funktioniert es wunderbar. Vielleicht kann ja jemand diesen Code gebrauchen. Ich entschuldige mich für eure Bemühungen (falls ihr was gemacht haben sollte :wink:). Grüße aus dem Rheinland |
AW: Programm vom Dienst starten mit mehr Rechten???
Hi,
ich habe mal deinen Code ohne die Anwendung der Jedi-Units umgeschrieben. Evtl. benötigt den noch irgendwer.
Code:
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; function CreateProcess4LoggedOnUser(const cmd: String): Cardinal; implementation {$R *.dfm} uses TlHelp32; function CreateProcess4LoggedOnUser(const cmd: String): Cardinal; var hToken : THandle; newToken : THandle; blub : Cardinal; aSessionId : Cardinal; aStartup : Windows.TStartupInfo; aPI : Windows.TProcessInformation; MyEnv : Pointer; bla : DWORD; f: textfile; root: string; var CreateEnvironmentBlock: function(lpEnvironment: PPointer; hToken: THandle; bInherit: BOOL): BOOL; stdcall; WTSGetActiveConsoleSessionId: function: DWord; stdcall; DestroyEnvironmentBlock: function(lpEnvironment: Pointer): BOOL; stdcall; begin @CreateEnvironmentBlock := GetProcAddress(LoadLibrary('userenv.dll'), 'CreateEnvironmentBlock'); @WTSGetActiveConsoleSessionId := GetProcAddress(LoadLibrary('kernel32.dll'), 'WTSGetActiveConsoleSessionId'); @DestroyEnvironmentBlock := GetProcAddress(LoadLibrary('userenv.dll'), 'DestroyEnvironmentBlock'); result := 0; root:= 'D:\temp.txt'; assignfile(f, root); rewrite(f); writeln(f, datetimetostr(now())+ ' - Report des Dienstes:'); if Windows.OpenProcessToken(GetCurrentProcess, TOKEN_ALL_ACCESS, hToken) then begin Writeln(f, 'OpenProcessToken Ok'); if Windows.ImpersonateLoggedOnUser(hToken) then begin WriteLn(f,'ImpersonateLoggedOnUser Ok'); if Windows.DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, nil, SecurityImpersonation, TOKENPRIMARY, newToken) then begin WriteLn(f,'DuplicateTokenEx Ok'); aSessionId := WTSGetActiveConsoleSessionId; bla := DWORD(aSessionId); if Windows.SetTokenInformation(newToken, Windows.TokenSessionId, @bla, SizeOf(DWORD)) then //Hier wird ein Fehler ausgelöst: (Error-Code 1314): Dem Client fehlt ein erforderliches Recht begin WriteLn(f,'SetTokenInformation Ok'); FillChar(aStartup,SizeOf(TStartupInfo),#0); FillChar(aPI,SizeOf(TProcessInformation),#0); aStartup.cb := SizeOf(TStartupInfo); aStartup.lpDesktop := 'WinSta0\Default'; MyEnv := nil; // Umgebungsvariablen werden vom Benutzer ermittelt. if CreateEnvironmentBlock(@MyEnv, newToken, false) then begin WriteLn(f,'CreateEnvironmentBlock Ok'); if Windows.CreateProcessAsUser(newToken, pChar(cmd), nil, nil, nil, true, NORMAL_PRIORITY_CLASS or CREATE_NEW_CONSOLE or CREATE_UNICODE_ENVIRONMENT, MyEnv, nil, aStartup ,aPI) then begin WriteLn(f,'CreateProcessAsUser Ok'); CloseHandle(aPI.hProcess); CloseHandle(aPI.hThread); end else begin result := GetLastError; WriteLn(f,'7: '+Sysutils.SysErrorMessage(result)); end; DestroyEnvironmentBlock(MyEnv); end else begin blub := Windows.GetLastError; WriteLn(f,'CreateEnvironmentBlock('+IntToStr(blub)+'): ' + Sysutils.SysErrorMessage(blub)); end; end else begin blub := Windows.GetLastError; WriteLn(f,'SetTokenInformation('+IntToStr(blub)+'): ' + Sysutils.SysErrorMessage(blub)); end; end else WriteLn(f,'DuplicateTokenEx: ' + Sysutils.SysErrorMessage(Windows.GetLastError)); end else WriteLn(f,'ImpersonateLoggedOnUser: ' + Sysutils.SysErrorMessage(Windows.GetLastError)); end else WriteLn(f,'OpenProcessToken: ' + Sysutils.SysErrorMessage(Windows.GetLastError)); close(f); end; end. |
AW: Programm vom Dienst starten mit mehr Rechten???
Wie verhält sich obiger Code, wenn mehrere Benutzer gleichzeitig an einem System angemeldet sind?
Eigentlich müsste man alle angemeldeten Benutzer durchgehen resp. alle Tokens durchgehen und dann bei jedem User (Oder nur bei gewünschten) einen Prozess starten. Mir gefällt die Möglichkeit sehr, von einem Dienst aus, einen Benutzerprozess zu starten darauf habe ich schon ein paar Mal gewartet, mal schauen was alles noch dabei rauskommt. |
AW: Programm vom Dienst starten mit mehr Rechten???
Hi,
die Version funktioniert nur fehlerfrei auf einem PC mit nur einem Anwender. Ich habe es heute auch schon auf einem Server gestartet und wie erwartet, ist es noch nicht ausgereift. Morgen werde ich mich weiter an den Quellcode wagen und es weiter anpassen. |
AW: Programm vom Dienst starten mit mehr Rechten???
Hallo zusammen,
in der heutigen DP-Nes Sektion ist ein Link auf weitere, nützliche Informationen zu diesem Thema: ![]() Eventuell bringt euch das weiter wenn es darum geht, für jeden angemeldeten Benutzer aus dem Dienst heraus ein Prozess zu starten. Gruss |
AW: Programm vom Dienst starten mit mehr Rechten???
Hi,
ja damit habe ich mich auch schon befasst. Ich denke aber, dass es an dem WTSGetActiveConsoleSessionId scheitern wird. Habe es mal mit WTSEnumerateSessions versucht, jedoch stehe ich dabei noch vor einem anderen Problem. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:30 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 by Thomas Breitkreuz