将wxWidgets的GUI写入DLL并在其他应用程序中调用

Post date: 2012/4/3 上午 05:29:19

wxWidtes是一种GUI库,结构跟MFC非常相似,但是明显比MFC少了很多宏并且真正意义上实现了跨平台。以前用MFC的时候知道MFC可以将GUI写入DLL,于是也用wxWidgets进行了尝试,也可能是不太了解wxWidgets的缘故,废了不少周折,在这里分享一下(也许用这个GUI的不太多,但是wxWidgets绝对是一个不比MFC差的GUI语言),如果有更好的方案,欢迎拿来分享。

wxWidgets跟MFC或者说QT很相似,都有一个叫某某app的东西来执行消息循环,并且在MFC和wxWidgets中,将main函数也封装了在里面,于是,在将wxWidgets写入DLL时有些需要注意的地方。首先,如果wxWidgets的GUI能够正常运行需要有窗口,还需要有消息循环,但普通的wxApp是带有main的,而dll中只有dllmain而没有实际的入口main,开始以为wxWidgets没有提供这种变态用法的解决方案,最后才发现,这群老外真不简单,什么都想到了。

IMPLEMENT_APP_NO_MAIN,就是声明一个wxApp,但是没有main函数,我了个去,这样将GUI写入DLL就完全没有问题了!但事情并不是那么完美,没有了main好多操作都需要自己来完成了,比如消息循环的启动!中文网站没有几个讲到这方面问题的,在维基上看到了一种解决方案,他是这样解决的:

IMPLEMENT_APP_NO_MAIN(wxDLLApp)

DWORD WINAPI ThreadProc(LPVOID lpParameter)

{

wxApp::SetInstance(new wxDLLApp());

wxEntry(GetModuleHandle(NULL),NULL,NULL,SW_SHOW);

return true;

}

BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)

{

switch (ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

ThreadId = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);

break;

case DLL_THREAD_ATTACH: break;

case DLL_THREAD_DETACH: break;

case DLL_PROCESS_DETACH:

wxEntryCleanup();

break;

}

return TRUE;

}

#endif

这样在加载DLL初就将消息循环写到了一条线程中,之所以这样做,我测试了一下,个人认为因为 wxEntry操作是阻塞的,是不退出的,如果不创建线程而直接写在DllMain中的话就导致DLL在加载阶段崩溃。而且我HOOK注入DLL的方式测试了一下,如果不用独立线程的来启动消息循环的话,wxApp退出时会导致其所在线程崩溃,可能这样说并不准确,但是至少看上去是这样,因此采用线程启动消息循环的方式是值得提倡的,但是上述代码中仍然存在问题,就是在加载了该DLL的进程退出时会崩溃,原因很简单,是因为消息循环线程尚未终止,解决方案就是在 case DLL_PROCESS_DETACH:中终止case DLL_PROCESS_ATTACH:中创建的线程,这样就不会引起程序的崩溃。这样就写一个普通的带有wxWidgets的GUI的DLL是没有问题了,这种启动方式是用DLLMain,因此在远程注入时可以采用,如果用RemoteThread的方式注入,上述方式完全可以胜任,但是在HOOK注入时就不同了,HOOK注入时注入时,需要有注入方和被注入方,注入方和被注入方都会加载这个DLL,如果将启动函数写在DLLMain中,注入方也不得不运行DLL中的程序,如果DLL是外挂或者病毒木马,岂不是自残啊!这里就提供个思路,并列举了我自己编码过程中发现的一些问题,具体的代码也不太好贴,就这样。。。

原文地址:http://wiki.wxwidgets.org/Creating_A_DLL_Of_An_Application