dedoki
dedoki

Reputation: 729

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?

Upvotes: 2

Views: 12293

Answers (2)

Pateman
Pateman

Reputation: 2757

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}

Upvotes: 7

Andreas
Andreas

Reputation: 1364

As you can read here

http://msdn.microsoft.com/en-us/library/windows/desktop/bb762153%28v=vs.85%29.aspx

it is up to the application to decide how to handle the SW_HIDE. Thus the application has to fetch the message and hide itself, as far as i see...

Upvotes: 2

Related Questions