Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

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

AW: Adminprozess starten und auf dessen Ende warten

  Alt 8. Aug 2012, 13: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)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

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