delphishellexecute

Delphi: shellexecute and sw_hide


I'm trying to run the application is hidden, but the application form is still visible.

ShellExecute(Handle, nil, 'app.exe', nil, nil, SW_HIDE);

How to run a hidden application in Delphi?


Solution

  • I would suggest using CreateProcess instead, because it returns the process ID of the newly launched application and you can use it to get the window's handle. Here's a function I have been using, maybe you can take away unnecessary fragments and adapt it to your needs?

    // record to store window information
    TWndInfo = record
      pid: DWord;
      WndHandle: HWND;
      width, height: Integer;
    end;
    PWndInfo = ^TWndInfo;
    
    {$HINTS OFF}
    { .: ExecNewProcess :. }
    function ExecNewProcess(const ProgramName: String;
      const StartHidden, WaitForInput: Boolean; out WndInfo: TWndInfo): Boolean;
    var
      StartInfo: TStartupInfo;
      ProcInfo: TProcessInformation;
      R: TRect;
      SL: TStringList;
    
      {$REGION 'EnumProcess'}
      function EnumProcess(hHwnd: HWND; lParam: Integer): Boolean; stdcall;
      var
        WndInfo: PWndInfo;
        pid: DWORD;
      begin
        Result := True;
    
        WndInfo := PWndInfo(lParam);
        if (WndInfo = nil) or (hHwnd = 0) then
          exit;
    
        GetWindowThreadProcessId(hHwnd, pid);
        if (pid = WndInfo.PID) then
        begin
          if (WndInfo.WndHandle = 0) and (IsWindowVisible(hHwnd)) then
            WndInfo.WndHandle := hHwnd;
          //Result := False;
        end;
      end;
      {$ENDREGION}
    
    begin
      Result := False;
    
      ZeroMemory(@StartInfo, SizeOf(TStartupInfo));
      ZeroMemory(@ProcInfo, SizeOf(TProcessInformation));
    
      StartInfo.cb := SizeOf(TStartupInfo);
      StartInfo.dwFlags := STARTF_USESTDHANDLES;
      if StartHidden then
      begin
        StartInfo.dwFlags := STARTF_USESHOWWINDOW or StartInfo.dwFlags;
        StartInfo.wShowWindow := SW_SHOWMINNOACTIVE;
      end;
    
      Result := CreateProcess(PChar(ProgramName), nil, nil, nil, False, 0, nil,
        nil, StartInfo, ProcInfo);
      try
        if Result then
        begin
          WndInfo.WndHandle := 0;
          WndInfo.PID := ProcInfo.dwProcessId;
    
          if WaitForInput then
            WaitForInputIdle(ProcInfo.hProcess, INFINITE);
    
          EnumWindows(@EnumProcess, Integer(@WndInfo));
          if (WndInfo.WndHandle <> 0) then
          begin
            if (StartHidden) then
              ShowWindow(WndInfo.WndHandle, SW_HIDE);
            Windows.GetWindowRect(WndInfo.WndHandle, R);
    
            WndInfo.Width := R.Right - R.Left;
            WndInfo.Height := R.Bottom - R.Top;
          end;
        end;
      finally
        CloseHandle(ProcInfo.hProcess);
        CloseHandle(ProcInfo.hThread);
      end;
    end;
    {$HINTS ON}