I used to use the function below to start and wait unil the end of a process.
It works fine for starting and waiting for 32 bits process on a 32 bits or 64 bits OS.
But on a 64 bits OS, it returns immediately when i launch a 64 bits process (WaitForSingleObject = WAIT_OBJECT_0).
For example, if my app (32 bits), launch mstsc.exe on a 32 bits OS it is ok but it don't wait on a 64 bits OS certainly because mstsc.exe is a 64 bits program.
Any solution ?
function gShellExecuteAndWait(
                              vHandle     : HWND;
                              vOperation  : string;
                              vFichier    : string;
                              vParametres : string;
                              vRepertoire : string;
                              vAffichage  : Integer;
                              vDuree      : DWORD;
                              var vErreur : string
                             ) : Boolean;
var
  vSEInfo  : TShellExecuteInfo;
  vAttente : DWORD;
begin
  // Initialisation
  Result   := True;
  vErreur  := '';
  vAttente := 0;
  // Initialisation de la structure ShellExecuteInfo
  ZeroMemory(@vSEInfo, SizeOf(vSEInfo));
  // Remplissage de la structure ShellExecuteInfo
  vSEInfo.cbSize       := SizeOf(vSEInfo);
  vSEInfo.fMask        := SEE_MASK_NOCLOSEPROCESS;
  vSEInfo.Wnd          := vHandle;
  vSEInfo.lpVerb       := PAnsiChar(vOperation);
  vSEInfo.lpFile       := PAnsiChar(vFichier);
  vSEInfo.lpParameters := PAnsiChar(vParametres);
  vSEInfo.lpDirectory  := PAnsiChar(vRepertoire);
  vSEInfo.nShow        := vAffichage;
  // L'exécution a réussi
  if ShellExecuteEx(@vSEInfo) then
  begin
    // Attendre la fin du process ou une erreur
    while True do
    begin
      case WaitForSingleObject(vSEInfo.hProcess, 250) of
        WAIT_ABANDONED :
        begin
          Result  := False;
          vErreur := 'L''attente a été annulée.';
          Break;
        end;
        WAIT_OBJECT_0 :
        begin
          Break;
        end;
        WAIT_TIMEOUT :
        begin
          // Initialisation
          vAttente := vAttente + 250;
          // Le délai d'attente n'a pas été atteint
          if vAttente < vDuree then
          begin
            Application.ProcessMessages();
          end
          // Le délai d'attente est dépassé
          else
          begin
            Result  := False;
            vErreur := 'Le délai d''attente a été dépassé.';
            Break;
          end;
        end;
        WAIT_FAILED :
        begin
          Result := False;
          vErreur := SysErrorMessage(GetLastError());
          Break;
        end;
      end;
    end;
  end
  // L'exécution a échoué
  else
  begin
    Result  := False;
    vErreur := SysErrorMessage(GetLastError());
  end;
end;
                My guess is that the following happens:
mstsc.exe.mstsc.exe then determines that it needs to start the 64 bit version of mstsc.exe, which it does, passing on any command line arguments, and then immediately terminates.This would explain why your new process immediately terminates.
Some possible solutions:
In the case of launching mstsc.exe from a 32 bits program on a 64 OS, I modified the function like this (it is a first try not the definitive version) ans it works like a charm !
Thank you @DavidHeffernan !
But be aware that if you don't know what process will be lauched (and its behavio) you need to consider @RemyLebeau global solution.
Thanks you !
function gShellExecuteAndWait(
                              vHandle     : HWND;
                              vOperation  : string;
                              vFichier    : string;
                              vParametres : string;
                              vRepertoire : string;
                              vAffichage  : Integer;
                              vDuree      : DWORD;
                              var vErreur : string
                             ) : Boolean;
var
  vSEInfo  : TShellExecuteInfo;
  vAttente : DWORD;
  IsWow64Process                 :function(aProcess: THandle; var aWow64Process: Bool): Bool; stdcall;
  Wow64DisableWow64FsRedirection :function(aOldValue :pointer) :Bool; stdcall;
  Wow64RevertWow64FsRedirection  :function(aOldValue :pointer) :Bool; stdcall;
  Wow64 :Bool;
  OldFs :pointer;
begin
  // Initialisation
  Result   := True;
  vErreur  := '';
  vAttente := 0;
  OldFS    := nil;
  IsWow64Process := Windows.GetProcAddress(Windows.GetModuleHandle('kernel32.dll'), 'IsWow64Process');
  if Assigned(IsWow64Process) then
  begin
    IsWow64Process(GetCurrentProcess, Wow64);
  end
  else
  begin
    Wow64 := False;
  end;
  if Wow64 then
  begin
    Wow64DisableWow64FsRedirection := GetProcAddress(Windows.GetModuleHandle('kernel32.dll'), 'Wow64DisableWow64FsRedirection');
    Wow64DisableWow64FsRedirection(OldFS);
  end;
  // Initialisation de la structure ShellExecuteInfo
  ZeroMemory(@vSEInfo, SizeOf(vSEInfo));
  // Remplissage de la structure ShellExecuteInfo
  vSEInfo.cbSize       := SizeOf(vSEInfo);
  vSEInfo.fMask        := SEE_MASK_NOCLOSEPROCESS;
  vSEInfo.Wnd          := vHandle;
  vSEInfo.lpVerb       := PAnsiChar(vOperation);
  vSEInfo.lpFile       := PAnsiChar(vFichier);
  vSEInfo.lpParameters := PAnsiChar(vParametres);
  vSEInfo.lpDirectory  := PAnsiChar(vRepertoire);
  vSEInfo.nShow        := vAffichage;
  // L'exécution a réussi
  if ShellExecuteEx(@vSEInfo) then
  begin
    // Attendre la fin du process ou une erreur
    while True do
    begin
      case WaitForSingleObject(vSEInfo.hProcess, 250) of
        WAIT_ABANDONED :
        begin
          Result  := False;
          vErreur := 'L''attente a été annulée.';
          Break;
        end;
        WAIT_OBJECT_0 :
        begin
          Break;
        end;
        WAIT_TIMEOUT :
        begin
          // Initialisation
          vAttente := vAttente + 250;
          // Le délai d'attente n'a pas été atteint
          if vAttente < vDuree then
          begin
            Application.ProcessMessages();
          end
          // Le délai d'attente est dépassé
          else
          begin
            Result  := False;
            vErreur := 'Le délai d''attente a été dépassé.';
            Break;
          end;
        end;
        WAIT_FAILED :
        begin
          Result := False;
          vErreur := SysErrorMessage(GetLastError());
          Break;
        end;
      end;
    end;
  end
  // L'exécution a échoué
  else
  begin
    Result  := False;
    vErreur := SysErrorMessage(GetLastError());
  end;
  if Wow64 then
  begin
    Wow64RevertWow64FsRedirection := GetProcAddress(Windows.GetModuleHandle('kernel32.dll'), 'Wow64RevertWow64FsRedirection');
    Wow64RevertWow64FsRedirection(OldFs);
  end;
end;
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With