如何从命令行或其他应用程序打开并引入桌面应用程序?

时间:2013-01-12 21:03:30

标签: c++ windows delphi desktop-application

有时需要从命令行打开新程序(例如Windows Powerpoint演示,因为幻灯片可以通过命令行“powerpnt.exe /s”打开),最大化此程序并将其作为第一个程序带到桌面前面用户可以查看和使用。如果用户在命令提示符中直接输入命令,则默认情况下会发生这种情况,因为命令提示符是活动窗口。

但问题是 - 如果从后台进程执行命令行,如何执行此操作 - 例如来自Windows Task Scehduler的自定义Windows服务应用程序 - 在这两种情况下,新窗口都不会作为第一个窗口。

目前我只能想象相当难的解决方案(其缺点是它们需要编码而不能在任务计划程序中使用):

  1. 可以尝试获取已打开程序的主窗口的句柄并操纵该窗口 - 例如最大化等等;
  2. 可以尝试完全放弃命令行,而是将Windows Office应用程序作为COM对象进行操作。
  3. 也许有更简单的方法?

2 个答案:

答案 0 :(得分:3)

您可以创建一个小型(非gui)启动器应用程序,它将为您调用新程序(我知道,这就是您所谓的硬解决方案),然后在任务计划程序上安排此启动程序。

这个启动器应用程序必须创建de process(CreateProcess function),然后从pID获取Window Handle ...使用窗口句柄你可以使用SetForegroundWindow来做你需要的,或者调用其他函数对于诸如最大化等等的事情。

由于你标记了delphi,我发布了一个可能的delphi实现。

function WindowFromPID(pID: Cardinal; VisibleWindow: Boolean): Cardinal;
type
  TProcData = record
    pID: Cardinal;
    pHandle: Cardinal;

    VisibleWindow: Boolean;
  end;

var 
  wPData: TProcData;

  function EnumProc(Handle: HWND; var pProcData: TProcData): Bool; stdcall;
  var pID: DWORD;
  begin
    Result := True;
    if pProcData.VisibleWindow then
      if not IsWindowVisible(Handle) then
        Exit;

    GetWindowThreadProcessId(Handle, @pID);
    if pID = pProcData.pID then begin
      if GetWindow(Handle, GW_OWNER) = 0 then begin
        pProcData.pHandle := Handle;
        Result := false;
      end;
    end;
  end;
begin
  wPData.pHandle := 0;
  wPData.pID := pID;
  wPData.VisibleWindow := VisibleWindow;

  EnumWindows(@EnumProc, Integer(@wPData));
  while (wPData.pHandle = 0) do begin
    Sleep(50);
    EnumWindows(@EnumProc, Integer(@wPData));
  end;

  Result := wPData.pHandle;
end;

procedure RunAndGetWindowHandle(const FileName, Params: String; const WindowState: Word): Cardinal;
var 
  SUInfo: TStartupInfo;
  CmdLine: String;
  ProcInfo: TProcessInformation
begin
  CmdLine := '"' + Filename + '"' + Params;
  FillChar(SUInfo, SizeOf(SUInfo), #0);
  with SUInfo do begin
    cb := SizeOf(SUInfo);
    dwFlags := StartF_UseShowWindow;
    wShowWindow := WindowState;
  end;

  if not CreateProcess(Nil, PChar(CmdLine), nil, nil, False, Create_New_Console Or Normal_Priority_Class, nil, PChar(ExtractFilePath(Filename)), SUInfo, ProcInfo) then
    raise Exception.Create('Error running process');

  if WaitForSingleObject(ProcInfo.hProcess, 50) <> WAIT_TIMEOUT then
    raise Exception.Create('Error running process!');

  CloseHandle(ProcInfo.hThread);
  while Result = 0 do begin
    Sleep(50);
    Result := WindowFromPID(ProcInfo.dwProcessId, true);
  end;
end;

...

var WindowHandle: Cardinal;
begin
  WindowHandle := RunAndGetWindowHandle("powerpnt.exe", " /s", SW_SHOWNORMAL);
  SetForegroundWindow(WindowHandle);
end;

希望这就是你需要的......如果不是那就抱歉。

最诚挚的问候。

答案 1 :(得分:0)

创建一个批处理文件,打开所需的程序并让任务计划程序运行

批处理文件将像用户直接在命令提示符中输入命令一样运行,您将获得所需的结果。