2014-07-26 63 views
-4

我有一个Win32应用程序创建一个简单的窗口,我需要从另一个程序(cryengine)调用该程序/窗口。我的应用程序开始于int WINAPI WinMain(...)。我该怎么做才能做到这一点?动态库,.exe,静态库?我想从另一个应用程序调用Win32应用程序,我该怎么办?

我原计划从我的其他程序中调用.exe。使用.dll会更好吗?

+0

['CreateProcess()'](http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v = vs.85).aspx)?更糟糕的是,使用DLL通常不能得到回答。这完全取决于你的具体用例。 –

+0

好的,谢谢。最后我会执行一个新的过程。 –

回答

2

您不必去DLL或静态库的方式从另一个程序启动您的程序。

使用CreateProcess,ShellExecuteShellExecuteEx

如果你的程序可以已经运行,那么你可以使用FindWindow来获得应用程序的窗口,并使用SendMessage告诉应用程序激活窗口发送一些信息。

但是,找到&激活(SetForegroundWindow)只会在任务栏中闪烁窗口按钮,以便获得用户的关注。这是由Windows完成的,因此其他应用程序不能中断并导致可用性问题。

+0

我会这样做,谢谢 –

1

使用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月)样本“自动运行”。

相关问题