AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Programmstart nach Update

Ein Thema von madas · begonnen am 15. Mär 2013 · letzter Beitrag vom 18. Mär 2013
Antwort Antwort
madas

Registriert seit: 9. Aug 2007
207 Beiträge
 
#1

Programmstart nach Update

  Alt 15. Mär 2013, 10:23
Hallo,

ich bin gerade dabei für unsere Programme eine Update-Komponente zu schreiben. Der Ablauf ist wie folgt:

- Updateliste wird von einem Webservice angefordet
- falls Updates vorhanden sind, wird ein Updater aus den Resourcen entpackt
- der Updater wird gestartet und die Updateliste wird an den Updater übergeben
- der Updater arbeitet die Liste ab und startet am Ende die Applikation neu

Problem dabei ist, dass der Updater je nach Installationort der Applikation mit Adminrechten gestartet wird, um z.B. Dateien unter C:\Programme\Applikation ersetzen zu können. Da der Updater in solch einem Fall mit Adminrechten läuft, wird aber auch am Ende die Applikation mit Adminrechten gestartet, was ja so nicht sein soll. Daher habe ich versucht die Applikation über CreateProcessAsUser zu starten. Jedoch läuft hier die Ermittlung des Usertoken per WTSQueryUserToken mit der Fehlermeldung ERROR_PRIVILEGE_NOT_HELD fehl. Nach intensiver Suche scheint es daran zu liegen, dass man WTSQueryUserToken nur aus einem Service heraus erfolgreich aufrufen kann.

Daher wäre nun meine Frage, wie ich es schaffe die Applikation mit den Rechten des aktuell angemeldeten Users vom Updater, der mit Adminrechten läuft, aus auszuführen. Das ganze ohne die Verwendung von WTSQueryUserToken.

Vielen Dank.

madas
  Mit Zitat antworten Zitat
CCRDude

Registriert seit: 9. Jun 2011
677 Beiträge
 
FreePascal / Lazarus
 
#2

AW: Programmstart nach Update

  Alt 15. Mär 2013, 10:26
  • Neuere Windows-Versionen haben einen Restart Manager.
  • Ist das nicht Aufgabe des Installers? Ist der selbstgeschrieben?
  • Ggfls. bei InnoSetup abschauen, gibt es im Source
  Mit Zitat antworten Zitat
madas

Registriert seit: 9. Aug 2007
207 Beiträge
 
#3

AW: Programmstart nach Update

  Alt 15. Mär 2013, 10:58
  • Neuere Windows-Versionen haben einen Restart Manager.
  • Ist das nicht Aufgabe des Installers? Ist der selbstgeschrieben?
  • Ggfls. bei InnoSetup abschauen, gibt es im Source
Ähm, es soll nicht der Rechner neugestartet werden. Sondern die Applikation, die upgedatet wird, soll nach dem Update wieder im normalen Userkontext vom Updater, der mit Adminrechten läuft, gestartet werden.

madas
  Mit Zitat antworten Zitat
CCRDude

Registriert seit: 9. Jun 2011
677 Beiträge
 
FreePascal / Lazarus
 
#4

AW: Programmstart nach Update

  Alt 15. Mär 2013, 11:00
Ja, das hatte ich schon verstanden. Wo habe ich etwas von Rechnerneustart geschrieben?
  Mit Zitat antworten Zitat
Morphie

Registriert seit: 27. Apr 2008
Ort: Rahden
630 Beiträge
 
#5

AW: Programmstart nach Update

  Alt 15. Mär 2013, 11:37
Kannst du nicht ein Zwischenprogramm einführen?

Dein Programm lädt Updates usw. herunter > Programm ruft anschließend das Zwischenprogramm auf

Das Zwischenprogramm hat zwei Aufgaben:
1. es startet das Updatesetup als Administrator und wartet darauf, dass es beendet wird.
2. Im Falle eines erfolgreichen Updates wird anschließend das eigentliche Programm gestartet. Da das Zwischenprogramm keine erweiterten Rechte hat, brauchst du hier auch keine weiteren Rechte o.ä. anfordern

Danach beendet sich das Zwischenprogramm und du siehst das geupdatete Programm wieder.
  Mit Zitat antworten Zitat
CCRDude

Registriert seit: 9. Jun 2011
677 Beiträge
 
FreePascal / Lazarus
 
#6

AW: Programmstart nach Update

  Alt 15. Mär 2013, 13:14
@Morphie: das verlagert das Problem doch nur. Ob der Updater nun, weil er elevated ist, eine elevierte Instanz des Programmes startet, oder eine elevierte Instanz des Zwischenprogrammes, dass dann eine elevierte Instanz des Programmes startet, macht keinen Unterschied

Da das Zwischenprogramm keine erweiterten Rechte hat,
Wieso nicht? Danach sucht madas ja eben - von einem elevierten Prozess aus einen Prozess zu starten, der es nicht ist.
  Mit Zitat antworten Zitat
Morphie

Registriert seit: 27. Apr 2008
Ort: Rahden
630 Beiträge
 
#7

AW: Programmstart nach Update

  Alt 15. Mär 2013, 13:56

Code:
Programm (normale Userrechte) > Zwischenprogramm (normale Userrechte) > Startet Setup mit erweiterten Rechten (UAC poppt auf)
                                                                      > Startet das ursprüngliche Programm (normale Userrechte)
Das Zwischenprogramm läuft also in dem gleichen Kontext wie das ursprüngliche Programm. Daher kann es das Programm nach dem Setup auch einfach ganz normal starten.
Erst das Setup bekommt erweiterte Rechte, ruft aber nach dem Setup kein Programm selbst auf.
  Mit Zitat antworten Zitat
madas

Registriert seit: 9. Aug 2007
207 Beiträge
 
#8

AW: Programmstart nach Update

  Alt 18. Mär 2013, 14:33
Die Quelltexte von Innosetup habe ich durch forstet, konnte jedoch nichts sinnvolles finden, was zu meiner Lösung beitragen wollte.
Nach weiterer Recherche im WWW bin ich auf folgenden Artikel gestoßen:

http://blogs.msdn.com/b/aaron_margos...vated-app.aspx

Ich habe dann versucht das Ganze mal nach Delphi zu portieren und es scheint auf den ersten Blick zu funzen. Die Funktion macht nur Sinn bzw. ist nur ausführbar, wenn das Programm in dem sie aufrufen wird mit Admin-Rechten läuft. Hier der Delphi Quelltext:

Delphi-Quellcode:
interface

  function RunsAsDesktopUser(appFileName, appParams, currDir: WideString): Boolean;

uses
  ..., JwaWindows, JwsclToken, JwsclPrivileges, ...;

implementation

function RunsAsDesktopUser(appFileName, appParams, currDir: WideString): Boolean;
const
  dwTokenRights: DWORD = TOKEN_QUERY or TOKEN_ASSIGN_PRIMARY or TOKEN_DUPLICATE or TOKEN_ADJUST_DEFAULT or TOKEN_ADJUST_SESSIONID;
var
  hProcessToken, hShellProcess, hShellProcessToken, hPrimaryToken: THandle;
  hHWND: HWND;
  dwPID: DWORD;
  tkp: TOKEN_PRIVILEGES;
  startupInfo: TSTARTUPINFOW;
  processInfo: TPROCESSINFORMATION;
  lastError: String;
  pAppParams: PWideChar;
begin
  Result := False;
  hProcessToken := THandle(nil); hShellProcess := THandle(nil); hShellProcessToken := THandle(nil); hPrimaryToken := THandle(nil);
  dwPID := 0; lastError := EmptyStr;
  ZeroMemory(@startupInfo, sizeof(startupInfo));
  startupInfo.cb := sizeof(startupInfo);
  startupInfo.lpDesktop := 'winsta0\default';
  startupInfo.dwFlags := STARTF_USESHOWWINDOW;
  startupInfo.wShowWindow := SW_SHOWDEFAULT;
  try
    if (OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hProcessToken)) then
    begin
      try
        tkp.PrivilegeCount := 1;
        if (LookupPrivilegeValue(nil, SE_INCREASE_QUOTA_NAME, tkp.Privileges[0].Luid)) then
        begin
          tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
          AdjustTokenPrivileges(hProcessToken, false, @tkp, SizeOf(TOKEN_PRIVILEGES), nil, nil);
          if (GetLastError <> ERROR_SUCCESS) then
          begin
            lastError := 'AdjustTokenPrivileges: ' + SysErrorMessage(GetLastError);
            Result := False;
            Exit;
          end;
        end;
      finally
        CloseHandle(hProcessToken);
      end;
    end else
    begin
      lastError := 'OpenProcessToken: ' + SysErrorMessage(GetLastError);
      Result := false;
      Exit;
    end;

    hHWND := GetShellWindow;
    if (hHWND = 0) then
    begin
      lastError := 'GetShellWindow: ' + SysErrorMessage(GetLastError);
      Result := False;
      Exit;
    end;

    GetWindowThreadProcessId(hHWND, @dwPID);
    if (hHWND = 0) then
    begin
      lastError := 'GetWindowThreadProcessId: ' + SysErrorMessage(GetLastError);
      Result := False;
      Exit;
    end;

    hShellProcess := OpenProcess(PROCESS_QUERY_INFORMATION, False, dwPID);
    if (hHWND = 0) then
    begin
      lastError := 'OpenProcess: ' + SysErrorMessage(GetLastError);
      Result := False;
      Exit;
    end;

    Result := OpenProcessToken(hShellProcess, TOKEN_DUPLICATE, hShellProcessToken);
    if (not Result) then
    begin
      lastError := 'OpenProcessToken: ' + SysErrorMessage(GetLastError);
      Exit;
    end;

    Result := DuplicateTokenEx(hShellProcessToken, dwTokenRights, nil, SecurityImpersonation, TokenPrimary, hPrimaryToken);
    if (not Result) then
    begin
      lastError := 'DuplicateTokenEx: ' + SysErrorMessage(GetLastError);
      Exit;
    end;

    if (appParams = EmptyWideStr) then
      pAppParams := nil
    else
      pAppParams := PWideChar(appFileName + ' ' + appParams);
    Result := CreateProcessWithTokenW(hPrimaryToken, 0, PWideChar(appFileName), pAppParams, 0, nil, PWideChar(currDir),   @startupInfo, @processInfo);
    if (not Result) then
    begin
      lastError := 'CreateProcessWithTokenW: ' + SysErrorMessage(GetLastError);
      Exit;
    end;

    Result := True;
  finally
    CloseHandle(hShellProcessToken);
    CloseHandle(hPrimaryToken);
    CloseHandle(hShellProcess);
    if (not Result) then
      ShowMessage(lastError);
  end;
end;
Grüße.

madas

PS: Falls es Verbesserungsvorschläge gibt nur raus damit.

Geändert von madas (18. Mär 2013 um 14:35 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:54 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