我有一个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通常不能得到回答。这完全取决于你的具体用例。 –
好的,谢谢。最后我会执行一个新的过程。 –