我们有一个基于插件的应用程序。每个插件都导出到动态库。由于某些原因,我们必须将每个插件作为一个新进程运行(每个插件都需要单独的可执行文件)。因此,我们要将.dll导出到一个新流程。
每个插件都包含构造函数,析构函数和一些函数。 如果没有导出,它就会以这种方式运行得很好(简化代码):
HINSTANCE lib = LoadLibrary(boost_path_to_dll);
// load the plugin class interface from the library using its factory functions
typedef fooClass *(*CreatePluginFuncDef)();
// pointer to constructor inside of plugin
CreatePluginFuncDef createPtr = (CreatePluginFuncDef)GetProcAddress(lib, "Create");
// pointer to destructor inside of plugin
typedef void(*DestroyPluginFuncDef)(fooClass*);
DestroyPluginFuncDef destroyPtr = (DestroyPluginFuncDef)GetProcAddress(lib, "Destroy");
// create new object
a = boost::shared_prt<fooClass>(pluginCreateFactoryPtr(), DestroyPluginFuncDef);
a->callSomeFunctionFromPlugin();
现在应该将插件导出到新进程。在网上,我发现了Wanderley Caloni Jr。的这个例子:
/**
* Run CreateProcess with specified parameters and get handle that allows
* to allocate memory and to run threads for this process.
*/
CreateAndGetProcessGodHandle(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine
)
{
HANDLE hRet = NULL;
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
TCHAR tzApplicationName[MAX_PATH] = _T("");
BOOL bRes;
// If string are empty, invalidate pointer and use the lpCommandLine.
if (lpApplicationName && !*lpApplicationName)
lpApplicationName = NULL;
else
ExpandEnvironmentStrings(lpApplicationName,
tzApplicationName,
sizeof(tzApplicationName));
bRes =
CreateProcess(*tzApplicationName ? tzApplicationName : lpApplicationName,
lpCommandLine,
NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL,
&si, &pi);
if (bRes != FALSE)
{
hRet = OpenProcess(PROCESS_CREATE_THREAD |
PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE |
PROCESS_VM_READ,
TRUE,
pi.dwProcessId);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return hRet;
}
/**
* Load DLL in another process.
*/
RemoteLoadLibrary(
HANDLE hProcess,
LPCTSTR lpFileName
)
{
LPCSTR tzLoadLibrary =
#ifdef UNICODE
"LoadLibraryW"
#else
"LoadLibraryA"
#endif
;
HMODULE hRet = NULL;
TCHAR tzFileName[MAX_PATH] = { 0 };
LPVOID lpCodeMem;
SIZE_T stCodeMem;
// Make a safe copy of the module path to be opened.
StringCbCopy(tzFileName, sizeof(tzFileName), lpFileName);
// Allocate memory in the another process.
stCodeMem = (_tcslen(tzFileName) + 1) * sizeof(TCHAR);
lpCodeMem = VirtualAllocEx(hProcess,
NULL,
stCodeMem,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (lpCodeMem != NULL)
{
// Write tzFileName in the allocated memory in the another process.
if (WriteProcessMemory(hProcess,
lpCodeMem,
tzFileName,
stCodeMem,
&stCodeMem))
{
HANDLE hThr;
DWORD dwThrId;
FARPROC fpLoadLibrary;
fpLoadLibrary =
GetProcAddress(GetModuleHandle(_T("Kernel32")), tzLoadLibrary);
// Create remote thread that loads the tzFileName module.
hThr =
CreateRemoteThread(hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)fpLoadLibrary,
(LPVOID)lpCodeMem,
0,
&dwThrId);
if (hThr != NULL)
{
// Get address where the module was loaded.
WaitForSingleObject(hThr, INFINITE);
GetExitCodeThread(hThr, (LPDWORD)&hRet);
CloseHandle(hThr);
}
}
VirtualFreeEx(hProcess, lpCodeMem, 0, MEM_RELEASE);
}
return hRet;
}
并在代码中使用它(再次简化):
//typedef HINSTANCE HMODULE; /* HMODULEs can be used in place of HINSTANCEs */
int iRet = 0;
TCHAR tzProgPath[MAX_PATH] = _T("%ComSpec%");
TCHAR tzProgArgs[MAX_PATH] = _T("");
TCHAR tzDllPath[MAX_PATH] = _T("paht_to_my_dll");
int opt;
/** Load DLL in another process. */
HANDLE hProc;
// Start process and get handle with powers.
// Starts cmd ( do you know, how to start it hidded ?! )
hProc = CreateAndGetProcessGodHandle(tzProgPath, tzProgArgs);
// edit:
// old post: seems to work properly ( not sure about it )
// new post: hDll has value 0x59a80000{unused=???}, but should know about loaded
// plugin ( so, the problem is inside of RemoteLoadLibrary() )
HMODULE hDll = RemoteLoadLibrary(hProc, tzDllPath);
// edit:
// old post: and from here the part, which is not working ( crash by this call )
// new post: no crash, but the createPrt has value = 0
// load the plugin class interface from the library using its factory functions
typedef fooClass *(*CreatePluginFuncDef)();
// pointer to constructor inside of plugin
CreatePluginFuncDef createPtr = (CreatePluginFuncDef)GetProcAddress(hDll, "Create");
// pointer to destructor inside of plugin
typedef void(*DestroyPluginFuncDef)(fooClass*);
DestroyPluginFuncDef destroyPtr = (DestroyPluginFuncDef)GetProcAddress(hDll, "Destroy");
...
你能看出我的错误吗? (也许不可能以这种方式调用dll函数?!)
您是否知道将dll导出到新流程的更好解决方案?
谢谢!
干杯 亚历克斯。