我有一個Win32應用程序創建一個簡單的窗口,我需要從另一個程序(cryengine)調用該程序/窗口。我的應用程序開始於int WINAPI WinMain(...)
。我該怎麼做才能做到這一點?動態庫,.exe,靜態庫?我想從另一個應用程序調用Win32應用程序,我該怎麼辦?
我原計劃從我的其他程序中調用.exe。使用.dll會更好嗎?
我有一個Win32應用程序創建一個簡單的窗口,我需要從另一個程序(cryengine)調用該程序/窗口。我的應用程序開始於int WINAPI WinMain(...)
。我該怎麼做才能做到這一點?動態庫,.exe,靜態庫?我想從另一個應用程序調用Win32應用程序,我該怎麼辦?
我原計劃從我的其他程序中調用.exe。使用.dll會更好嗎?
您不必去DLL或靜態庫的方式從另一個程序啓動您的程序。
使用CreateProcess,ShellExecute或ShellExecuteEx。
如果你的程序可以已經運行,那麼你可以使用FindWindow來獲得應用程序的窗口,並使用SendMessage告訴應用程序激活窗口發送一些信息。
但是,找到&激活(SetForegroundWindow)只會在任務欄中閃爍窗口按鈕,以便獲得用戶的關注。這是由Windows完成的,因此其他應用程序不能中斷並導致可用性問題。
我會這樣做,謝謝 –
使用DLL的主要原因是將其託管在與EXE相同的進程中。如果你想啓動另一個程序,那麼你想啓動另一個EXE。
雖然原則上這很容易,但這會產生潛在的問題。
首先,CreateProcess是啓動另一個EXE的最低級別的方式,但只有當目標程序以相同的權限級別運行時纔有效。對於Win32應用程序,您應該使用ShellExecuteEx。確保正確的當前工作目錄也存在問題。
這裏的代碼相當強大的片段,您可以使用:
BOOL Autorun::SpawnProcess(const WCHAR* szExePath, const WCHAR* szExeArgs)
{
if(!szExePath)
return FALSE;
// NOTE: szExeArgs can be NULL.
// Get working directory from executable path.
WCHAR szDirectory[MAX_PATH];
wcscpy_s(szDirectory, szExePath);
PathRemoveFileSpec(szDirectory);
// ShellExecute or ShellExecuteEx must be used instead of CreateProcess
// to permit the shell to display a UAC prompt asking for consent to
// elevate when the target executable's manifest specifies a run level
// of "requireAdministrator".
//
// You can only use CreateProcess if you know that the application you
// are spawning will be at the same run level as the current process.
// Otherwise, you will receive ERROR_ACCESS_DENIED if the elevation
// consent could not be obtained.
SHELLEXECUTEINFO info;
ZeroMemory(&info, sizeof(info));
info.cbSize = sizeof(info);
info.lpVerb = L"open";
info.fMask = SEE_MASK_FLAG_NO_UI;
info.lpFile = szExePath;
info.lpParameters = szExeArgs;
info.lpDirectory = szDirectory;
info.nShow = SW_SHOW;
if(!ShellExecuteEx(&info))
return FALSE;
return TRUE;
}
這裏的另一個挑戰是,如果你想嘗試跟蹤子進程的「工作」。一些發射器試圖使用「作業對象」來跟蹤子進程本身可能啓動的所有內容。特別的問題是LAUNCHER - > TARGET PROGRAM - > REAL PROGRAM和原來的TARGET PROGRAM退出。問題在於「作業對象」被Windows程序兼容性助手隱式使用,並且無法將進程添加到多個作業。確保創建過程的唯一可靠方法不會添加到PCA作業中,以確保您使用的所有程序都具有適當的清單元素。有關更多信息,請參閱此blog post。
對於只關心孩子的過程本身簡化的情況下,可以使用這樣的代碼片段:
BOOL Autorun::SpawnProcessAndWait(const WCHAR *szExePath, const WCHAR *szExeArgs, DWORD *pdwExitCode)
{
if(!szExePath)
return FALSE;
// NOTE: szExeArgs can be NULL.
// NOTE: pExitCode can be NULL.
// Get working directory from executable path.
WCHAR szDirectory[MAX_PATH];
wcscpy_s(szDirectory, szExePath);
PathRemoveFileSpec(szDirectory);
// See SpawnProcess for information why ShellExecute or ShellExecuteEx
// must be used instead of CreateProcess.
SHELLEXECUTEINFO info;
ZeroMemory(&info, sizeof(info));
info.cbSize = sizeof(info);
info.lpVerb = L"open";
info.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS;
info.lpFile = szExePath;
info.lpParameters = szExeArgs;
info.lpDirectory = szDirectory;
info.nShow = SW_SHOW;
if(!ShellExecuteEx(&info))
return FALSE;
// Wait for process to finish.
WaitForSingleObject(info.hProcess, INFINITE);
// Return exit code from process, if requested by caller.
if(pdwExitCode)
GetExitCodeProcess(info.hProcess, pdwExitCode);
CloseHandle(info.hProcess);
return TRUE;
}
順便說一句,這兩個代碼片段從傳統的DirectX SDK來(2010年6月)樣本「自動運行」。
['CreateProcess()'](http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v = vs.85).aspx)?更糟糕的是,使用DLL通常不能得到回答。這完全取決於你的具體用例。 –
好的,謝謝。最後我會執行一個新的過程。 –