3

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

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

目前我只能想象非常困难的解决方案(其缺点是它们需要编码并且不能从任务计划程序中使用):

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

也许有更简单的方法?

4

2 回答 2

4

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

这个启动器应用程序必须创建 de 进程(CreateProcess 函数),然后从 pID 中获取窗口句柄...使用窗口句柄,您可以使用 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;

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

最好的祝福。

于 2013-01-12T21:49:22.573 回答
0

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

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

于 2013-01-12T22:07:49.677 回答