Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

AW: Adminprozess starten und auf dessen Ende warten

  Alt 8. Aug 2012, 14:26
Was passiert denn unter XP, wenn es mit runas gestartzet wird?

Hab's jetzt erstmal so umgesetzt und noch einen Warte/Abbrechdialog integriert, welcher von der Funktion einem DelayDelay(3*60*1000) entspricht, nur eben mit Abbruch, wenn vorher fertig.

Nun muß nur noch ein Problemchen mit dem Netsharelaufwerk gefunden werden.
Das auszuführende Programm wird zwar vorher nach %TEMP% kopiert und dort ausgeführt, aber es muß auf eine Datei im Adminverzeichnis zugreifen, welche dann global installiert werden müste, aber das ist/wird eine andere Frage.

Zumindestens scheint das Programm nun endlich zu starten und das mit UAC.

Delphi-Quellcode:
function DoExecuteAndWait(Filename, Parameter: string; StartParams: TExecuteParams = []): LongWord{ExitCode};
var
  SEI: TShellExecuteInfo;
  StartInfo: TStartupInfo;
  ProcInfo: TProcessInformation;
  LastError, Len: LongWord;
  Error: EOSError;
  Dialog: TForm;
  Title, Username: string;
  Domain, Password: string;
  Host, Question: string;
  StartTime: LongWord;
  Objects: array[0..1] of THandle;
  Event: THandle;
begin
  Result := LongWord(-1);
  FillChar(SEI, SizeOf(SEI), 0);
  SEI.cbSize := SizeOf(SEI);
  SEI.fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_NO_UI;
  if epOnlyWaitToIdleInput in StartParams then
    SEI.fMask := SEI.fMask or SEE_MASK_WAITFORINPUTIDLE;
  SEI.Wnd := Application.MainFormHandle;
  If epStartWithLogon in StartParams then
    SEI.lpVerb := 'runas';
  SEI.lpFile := PChar(Filename);
  SEI.lpParameters := PChar(Parameter);
  SEI.lpDirectory := PChar(ExtractFileDir(Filename));
  SEI.nShow := SW_SHOWNORMAL;
  if not ShellExecuteEx(@SEI) then
    RaiseLastOSError;
  try
    if StartParams * [epOnlyWaitToIdleInput, epNoWait] = [] then
      if GetCurrentThreadId = MainThreadID then begin
        Dialog := CreateMessageDialog('Warte auf ' + Filename, mtInformation, [mbAbort]);
        try
          Dialog.Show;
          Title := Dialog.Caption;
          Event := CreateEvent(nil, False, False, nil); // dieses Event reagiert auf Messages im MainThread
          try
            Objects[0] := Event;
            Objects[1] := SEI.hInstApp;
            while True do begin
              Dialog.Caption := Format('[%ds] ', [LongInt(GetTickCount - StartTime) div 1000]) + Title;
              Application.ProcessMessages;
              if Dialog.ModalResult <> mrNone then
                raise Exception.Create('DoExecuteAndWait: ' + Filename + sLineBreak + 'Abbruch durch den Benutzer.');
              if Application.Terminated then
                raise Exception.Create('DoExecuteAndWait: ' + Filename + sLineBreak + 'Programm wird beendet');
              case MsgWaitForMultipleObjects(2, Objects, False, 5*60000, QS_ALLINPUT) of
                WAIT_OBJECT_0: ; // Programm hat irgendwas zu erledigen
                WAIT_OBJECT_0+1: Break; // Programm beendet
                WAIT_TIMEOUT: ; // 5 Minuten lang nichts passiert? (ich glaub die Welt ist untergegangen)
                WAIT_FAILED: raise Exception.Create('DoExecuteAndWait: ' + Filename + sLineBreak + 'Es war nicht möglich auf die Anwendung zu warten.');
                else raise Exception.Create('DoExecuteAndWait: ' + Filename + sLineBreak + 'Unbekannter Fehler.');
              end;
            end;
            if not GetExitCodeProcess(SEI.hInstApp, Result) then
              Result := LongWord(-1);
          finally
            CloseHandle(Event);
          end;
        finally
          Dialog.Free;
        end;
      end else
        case WaitForSingleObject(SEI.hInstApp, 3*60000) of
          WAIT_OBJECT_0: if not GetExitCodeProcess(SEI.hInstApp, Result) then
                           Result := LongWord(-1);
          WAIT_TIMEOUT: raise Exception.Create('DoExecuteAndWait: ' + Filename + sLineBreak + 'Gestartete Anwendung reagiert nicht. (innerhalb von 3 Minuten)');
          WAIT_FAILED: begin
                           LastError := GetLastError;
                           raise Exception.Create('DoExecuteAndWait: ' + Filename + sLineBreak + SysErrorMessage(LastError));
                         end;
          else raise Exception.Create('DoExecuteAndWait: ' + Filename + sLineBreak + 'Unbekannter Fehler.');
        end;
  finally
    CloseHandle(SEI.hInstApp);
  end;
  Exit;
(ach ja, nicht wundern, aber ich hab die lokalen Variablen noch nicht aufgeräumt
und ich hasse die Codeformatiewrung im Forum, welche einfah so leerzeichen löscht und die Formatierung zerstört)
$2B or not $2B

Geändert von himitsu ( 8. Aug 2012 um 14:31 Uhr)
  Mit Zitat antworten Zitat