2013-01-12 58 views
2

有時需要從命令行打開新程序(例如Windows Powerpoint演示文稿,因爲幻燈片可以通過命令行「powerpnt.exe /s」)打開,最大化該程序並將其作爲用戶可以看到並使用的第一個程序放在桌面前。如果用戶直接在命令提示符中輸入命令,則會出現這種情況,因爲命令提示符是活動窗口。如何從命令行或其他應用程序打開並引入桌面應用程序?

但問題是 - 如何做到這一點,如果從後臺進程執行命令行 - 例如來自Windows Task Scehduler的自定義Windows服務應用程序 - 在這兩種情況下,都不會將新窗口作爲第一個窗口。

目前我能想象只有相當困難的解決方案(其缺點是,他們所需要的編碼,他們不能從任務計劃使用):

  1. 一個可以嘗試獲取的主窗口的句柄打開的程序和操縱這個窗口 - 例如最大化等等;
  2. 可以嘗試放棄命令行,而是將Windows Office應用程序作爲COM對象進行操作。

也許有更簡單的方法嗎?

+0

我不確定你在這裏找什麼。我會建議[SetForegroundWindow](http://msdn.microsoft.com/en-us/library/windows/desktop/ms633539%28v=vs.85%29.aspx),但是在#1之後。我推測你已經發布了delphi標籤,因爲你正在尋找一種編碼解決方案,而這很可能除非你能夠做一個COM解決方案。 – Glenn1234

回答

3

您可以創建一個小型(非gui)啓動器應用程序,爲您調用新程序(我知道,這就是您稱之爲硬解決方案),然後在任務調度器上調度此啓動器。

這個啓動器應用程序將不得不創建de過程(CreateProcess function),然後從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; 

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

最好的問候。

+0

這正是我所期待的。謝謝! – TomR

+0

@TomR,你可能得到的代碼缺少我剛添加的WindowFromPID函數。我沒有注意到它一開始就錯過了,對不起。 – GabrielF

+0

@TomR如果這對你有幫助,學習[http://meta.stackexchange.com/questions/5234](how接受答案)並將其標記爲你的問題的接受答案。 – jachguate

0

創建一個批處理文件,打開所需的程序並讓Task Scheduler運行

批處理文件將運行,就像用戶直接將命令輸入命令提示符一樣,您將得到所需的結果。

相關問題