Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Problem mit ShellExecute und Windows 8 (https://www.delphipraxis.net/172711-problem-mit-shellexecute-und-windows-8-a.html)

Codewalker 18. Jan 2013 14:51

Problem mit ShellExecute und Windows 8
 
Hallo zusammen.

Ich nutze bisher folgenden Code, um einen Prozess mit Parametern zu starten und auf die Beendigung zu warten (ich nutze vorgabebeding einige Returncodes):
Delphi-Quellcode:
function ExecuteAndWait(Filename, Params: Widestring;
                     WindowState: Word = SW_SHOWNORMAL): Integer;
var
  ShExecInfoW: SHELLEXECUTEINFOW;
  r : Cardinal;
  ExitCode: Cardinal;
  res: Boolean;
begin
  Result := -50;
  if Filename = '' then Exit;
  if not FileExists(FileName) then
  begin
    Exit(-100);
  end;

  ShExecInfoW.Wnd := GetForegroundWindow;
  ShExecInfoW.cbSize := sizeof(SHELLEXECUTEINFOW);
  ShExecInfoW.fMask := SEE_MASK_NOCLOSEPROCESS;
  ShExecInfoW.lpVerb := 'open';
  ShExecInfoW.lpFile := PWideChar(Filename);
  ShExecInfoW.lpParameters := PWideChar(Params);
  ShExecInfoW.lpDirectory := PWideChar(ExtractFileDir(Filename));
  ShExecInfoW.nShow := WindowState;
  res := ShellExecuteExW(@ShExecInfoW);

  try
    if res then
    begin
      r := WaitForSingleObject(ShExecInfoW.hProcess, INFINITE);
      if not GetExitCodeProcess(ShExecInfoW.hProcess, ExitCode)
        then Result := -1;
    end;
  finally
    CloseHandle(ShExecInfoW.hProcess);
    Result := ExitCode;
  end;
end;
Das klappte bisher sehr gut, aber unter Windows 8 friert mein Programm ein und der andere Prozess wird nicht gestartet. Wenn ich dann mein Programm über den Debugger kille, dann wird endlich (aber zu spät natürlich) der andere Prozess gestartet. Was habe ich nicht bedacht?

dunningkruger 18. Jan 2013 15:19

AW: Problem mit ShellExecute und Windows 8
 
Bei mir funktionieren manche Programme erst dann korrekt, wenn ich sie nicht aus der IDE oder völlig ohne laufende IDE starte. Probiers mal aus!

DeddyH 18. Jan 2013 15:20

AW: Problem mit ShellExecute und Windows 8
 
BTW: Wäre
Delphi-Quellcode:
if res then
  try
nicht sinnvoller?

Codewalker 18. Jan 2013 15:30

AW: Problem mit ShellExecute und Windows 8
 
Zitat:

Zitat von DeddyH (Beitrag 1199651)
BTW: Wäre
Delphi-Quellcode:
if res then
  try
nicht sinnvoller?

Ja, ich denke du hast Recht

Edit: Ändert aber am Verhalten erstmal nix.

DeddyH 18. Jan 2013 15:46

AW: Problem mit ShellExecute und Windows 8
 
Wo genau bleibt das Programm denn stehen? Der Prozess scheint ja noch gestartet zu werden.

Codewalker 18. Jan 2013 15:59

AW: Problem mit ShellExecute und Windows 8
 
Er bleibt beim
Delphi-Quellcode:
WaitForSingleObject
hängen, aber nicht immer. Ich werde mich da mal in Ruhe durchsteppen ...

Edit: Scheint wohl mit Berechtigung / UAC zusammenzuhängen. Weiß jemand, wie ich mit ShellExecute & UAC das sauber umsetzen kann, ein anderes Programm als Admin zu starten und auf dessen Beendigung zu warten?

DeddyH 18. Jan 2013 16:29

AW: Problem mit ShellExecute und Windows 8
 
Hilft Dir MSDN-Library durchsuchenCreateProcessWithLogonW weiter?

dunningkruger 18. Jan 2013 16:50

AW: Problem mit ShellExecute und Windows 8
 
Zitat:

Zitat von dunningkruger (Beitrag 1199650)
Bei mir funktionieren manche Programme erst dann korrekt, wenn ich sie nicht aus der IDE oder völlig ohne laufende IDE starte. Probiers mal aus!

Hast Du aber gelesen, oder :twisted: ?

Codewalker 18. Jan 2013 17:05

AW: Problem mit ShellExecute und Windows 8
 
Zitat:

Zitat von dunningkruger (Beitrag 1199672)
Zitat:

Zitat von dunningkruger (Beitrag 1199650)
Bei mir funktionieren manche Programme erst dann korrekt, wenn ich sie nicht aus der IDE oder völlig ohne laufende IDE starte. Probiers mal aus!

Hast Du aber gelesen, oder :twisted: ?

Ja, ist mir beim Edit durchgegangen. Hat nichts geändert (wäre auch noch ärgerlicher gewesen)

Dalai 18. Jan 2013 18:17

AW: Problem mit ShellExecute und Windows 8
 
Zitat:

Zitat von Codewalker (Beitrag 1199661)
Weiß jemand, wie ich mit ShellExecute & UAC das sauber umsetzen kann, ein anderes Programm als Admin zu starten und auf dessen Beendigung zu warten?

Benutze als Verb entweder 'runas' oder 'runasuser'. Ersteres sorgt auf Windows bis einschl. XP für den Dialog 'Ausführen als anderer Nutzer', ab Vista aber für einen UAC-Dialog, letzteres sorgt bei Windows ab Vista für 'Ausführen als anderer Nutzer' (weiß nicht mehr, wie XP darauf reagiert).

Ergänzung:
Hab ich ja völlig vergessen, dass ich selber Probleme hatte, auf das Ende eines solchen 'elevated' Prozesses zu warten, wie ich in diesem Thema ausführte... Es kann also sein, dass ShellExecuteEx auch bei aktiver UAC nicht wartet.

MfG Dalai

musicman56 18. Jan 2013 19:30

AW: Problem mit ShellExecute und Windows 8
 
Hallo,

das "Warten" funktioniert bei mir mit der folgenden Funktion mit allen Betriebssystemen einwandfrei:

Delphi-Quellcode:
function RuWin_ShellExec(aHandle: HWND; FileName, Parameters, Directory: string;
                         ShowCmd: Integer; AsAdmin, Wait: boolean): Boolean;
var
  SEI: TShellExecuteInfo;
begin
  FillChar(SEI, SizeOf(SEI), #0);
  SEI.cbSize := SizeOf(SEI);
  SEI.Wnd := aHandle;
  SEI.fMask := SEE_MASK_NOCLOSEPROCESS;
  {-Bis zu XP "AsAdmin" automatisch ignorieren-}
  if RunningWinVer <= WinXPProf then AsAdmin := false;
  if AsAdmin
  then SEI.lpVerb := 'runas'
  else SEI.lpVerb := 'open';
  SEI.lpFile := PChar(FileName);
  SEI.lpParameters := PChar(Parameters);
  SEI.lpDirectory := PChar(Directory);
  SEI.nShow := ShowCmd;
  Result := ShellExecuteEx(@SEI);
  if Result then
  if Wait then begin
    if SEI.hProcess > 32 then begin
      WaitForInputIdle(SEI.hProcess, INFINITE);
      WaitForSingleObject(SEI.hProcess, INFINITE);
    end;
  end;
  CloseHandle(SEI.hProcess);
end;
Das einzige Problem, was mit dem "Warten" eigentlich nichts zu tun hat, ist dieser blöde User-Dialog unter XP wenn man "runas" verwendet, der dummerweise noch eine Checkbox beinhaltet die voreingestellt mit verminderten Rechten ausführt. Darum die OS-Prüfung
Code:
if RunningWinVer <= WinXPProf

QuickAndDirty 19. Jan 2013 11:19

AW: Problem mit ShellExecute und Windows 8
 
WaitForSingleObject
funktioniert nur für Anwendungen mit nur einem "Fenster" oder mit ConsolenAnwendungen.

Deswegen habe ich das in "meiner" Funktion (zusammen mit ungefähr allen DP mitgliedern entwickelt) durch MsgWaitForMultipleObject ersetzt!

Delphi-Quellcode:
function ExecAndWait(Filename, Params: string; TimeOut:Integer=-1 ; WindowState: word = SW_SHOWNORMAL): boolean;
var
  ShExecInfo: SHELLEXECUTEINFO;
  started,r : Cardinal;

  const
  SEE_MASK_NOASYNC= $100;
begin
  Result := false;
  if Filename = '' then
    exit;
  if not FileExists(FileName) then
  Begin
    ShowMessage('Datei nicht existent!');
    Exit;
  End;
  ZeroMemory(@ShExecInfo, SizeOf(ShExecInfo));
  ShExecInfo.Wnd := application.Handle;
  ShExecInfo.cbSize := sizeof(SHELLEXECUTEINFO);
  ShExecInfo.fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_NOASYNC;
  ShExecInfo.lpVerb := 'open';
  ShExecInfo.lpFile := PChar(Filename);
  ShExecInfo.lpParameters := PChar(Params);
  ShExecInfo.lpDirectory := PChar(ExtractFileDir(Filename));
  ShExecInfo.nShow := WindowState;
  Result := ShellExecuteEx(@ShExecInfo);
  if Result then
  begin
    started := Gettickcount;
    repeat
      R := MsgWaitForMultipleObjects(1, ShExecInfo.hProcess, False, TimeOut, QS_ALLINPUT);
      if r <> WAIT_OBJECT_0 then
        Application.ProcessMessages;
    until (r = WAIT_OBJECT_0) or ( (Timeout >-1) and ( Started + TimeOut < GetTickCount )) ;
    if (timeout > -1) then  
      Result := not( Started + TimeOut < GetTickCount );
    CloseHandle(ShExecInfo.hProcess);
  end
  else
    Showmessage(SysErrorMessage(GetLastError));

End;

musicman56 19. Jan 2013 12:18

AW: Problem mit ShellExecute und Windows 8
 
Hallo,

ich will ja nicht meckern oder kritisieren, besonders nicht wenn so viele DP-User daran beteiligt waren. Gibt es denn für . . .

Delphi-Quellcode:
      if r <> WAIT_OBJECT_0 then
        Application.ProcessMessages;
. . . keine andere Lösung? Wenn ich eine externe App aufrufe, und darauf warte bis sie beendet wird, dann würde ich erwarten, dass in meiner aufrufenden App nichts passiert, was ja gerade durch Application.ProcessMessages passiert.

Eine Frage hätt ich noch: Was bedeutet . . .
Zitat:

funktioniert nur für Anwendungen mit nur einem "Fenster" oder mit ConsolenAnwendungen.
Ich rufe beispielsweise eine MDI-App damit auf, und das funktioniert. Vielleicht hab ich was nicht verstanden :roll:

QuickAndDirty 19. Jan 2013 13:06

AW: Problem mit ShellExecute und Windows 8
 
Application.Processmessages sorgt dafür das die aufrufende Anwendung noch reagiert (z.b. auf verschieben). Sonst steht da hinterher wenn du in die anwendung klickst "Anwendnung Reagiert nicht mehr soll sie geschlossen werden?"

Aber du kannst da auch sleep oder nop reinpacken.


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:00 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