一种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, _T("COMServer"), MB_OK);
}
else
{
MessageBox(NULL, _T("Func failed"), _T("COMServer"), MB_OK);
}
return S_OK;
}
在IDL文件中导出我们的包装函数
这样就可以了~
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
可以查看注册表确认是否注册成功。
运行一下,见证奇迹的时刻到啦~