一种x64进程使用32位 DLL的方法
有的时候要用第三方的DLL,但是仅有32位版本,自己开发的程序又必须是是64位的,这下头就疼了。。。。
其实反之也是一样的头疼,这时候有什么办法呢?
一个典型的思路就是用32位进程加载DLL,然后64位进程跟32位进程通讯。
其实微软已经有了COM技术来帮我们解决这个问题:
1.创建一个进程外COM服务器。
2.使用COM服务器的相关接口去包装32位DLL的接口。
3.64位进程调用32位COM服务器接口。
这里面的关键就是如何创建一个进程外COM服务器
使用ATL模板去创建是一种非常快捷方便的方式
EXE才是进程外Com 服务,另外勾选另一个选项可以减少一个代理project
然后增加一个类作
这时候编译一下 会发现一个错误,
这是因为编译之后会去注册com组件,因为没有权限儿报错,如果使用管理员权限开vs就不会有这个问题。
接着在类中加入包裹DLL的代码
STDMETHODIMP CCLeenSimple::LoadDll32() { m_hDll = LoadLibrary(_T("TestDll.dll")); if (m_hDll) { m_pFun = (GCUN)GetProcAddress(m_hDll,"GetCurrentUserName"); if (m_pFun != NULL) return S_OK; } else GetLastError(); return E_FAIL; } STDMETHODIMP CCLeenSimple::Launch(TCHAR szTitile[MAX_PATH]) { HRESULT hr = LoadDll32(); BOOL bRet = FALSE; TCHAR szUserName[MAX_PATH] = { 0 }; if (Failed(hr)) { OutputDebugString(_T("LoadDll32 fail")); MessageBox(NULL,_T("LoadDll32 fail"),_T("COMServer"),MB_OK); } else { bRet = m_pFun(szUserName); } if (bRet) { OutputDebugString(szUserName); MessageBox(NULL,szUserName,MB_OK); } else { MessageBox(NULL,_T("Func Failed"),MB_OK); } return S_OK; }
这样就可以了~
DLL中的函数
EXTERN_C BOOL WINAPI GetCurrentUserName(TCHAR* pszbuff) { BOOL bRet = FALSE; TCHAR szUserNameBuffer[MAX_PATH]; DWORD dwUserNameSize = MAX_PATH; bRet = GetUserName(szUserNameBuffer,&dwUserNameSize); if (bRet) { _tcscpy_s(pszbuff,dwUserNameSize,szUserNameBuffer); } return bRet; }
客户端测试代码
HRESULT hr = CoInitialize(NULL); ICLeenSimple* pILeenTest; //CComPtr<ILeenTest> pILeenTest; TCHAR szUserName[MAX_PATH] = { 0 }; if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_CLeenSimple,NULL,CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,__uuidof(ICLeenSimple),(void**)&pILeenTest); if (SUCCEEDED(hr)) { pILeenTest->Launch(szUserName); } }
测试前记得先注册COM server
命令
Out_Process.exe /RegServer
反注册
Out_Process.exe /UnregServer
运行一下,见证奇迹的时刻到啦~