我使用Visual Studio 2010用C ++开发了Pro-Proc-COM-Server,以避免Shellextensions(http://blog.mattmags.com/2007/06/30/accessing-32-bit-dlls-from-64-bit-code/)中的64位和32位问题。
我在IDL文件中描述了像这里的接口(http://msdn.microsoft.com/en-us/library/ms686605%28v=VS.85%29.aspx):
ojit_pre
该文件为我生成了一个Proxy / Stub-DLL,我也注册了该文件以使用标准Marshaller方法。
如果我现在打电话
import "unknwn.idl";
[
object,
uuid("xx"),
helpstring("IShellServerx86-Interface")
]
interface IShellServerx86 : IUnknown
{
HRESULT ShowFileInfo([in]BSTR file, [out]BSTR* htmlFile, [in]BSTR pathChar);
};
服务器已创建,我可以调用该方法
IShellServerx86* pShellServer = NULL;
CoCreateInstance(__uuidof(CShellServerx86), NULL, CLSCTX_LOCAL_SERVER,
__uuidof(IShellServerx86), (void**)&pShellServer);
并使用创建的参数(客户端):
HRESULT CShellServerx86::ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathChar)
在客户端中,BSTR是正确生成的,但是当调用COM方法(他找到它)并且我调试到dllhost.exe时,参数无效,就像选择了错误的编码一样。我试图为整个项目设置“ Unicode”,但没有任何变化。
我忘记了任何设置还是应该尝试其他数据类型进行编组?
预先感谢您的帮助。
编辑:
客户端的实现是:
BSTR filebstr = ::SysAllocString(A2OLE(file));
BSTR pathBstr = ::SysAllocString(A2OLE(pathChar));
BSTR htmlFileBstr = ::SysAllocString(A2OLE(""));
服务器方法声明如下:
int CShellWrapperx64Module::ShowFileInfo(IN const char* file,
OUT VARIANT &htmlFile,
IN const char* pathChar)
{...
::CoInitialize(NULL);
IShellServerx86* pShellServer = NULL
hr = ::CoCreateInstance(__uuidof(CShellServerx86), NULL,
CLSCTX_LOCAL_SERVER, __uuidof(IShellServerx86),
(void**)&pShellServer);
BSTR filebstr = ::SysAllocString(A2OLE(file));
BSTR pathBstr = ::SysAllocString(A2OLE(pathChar));
BSTR htmlFileBstr = ::SysAllocString(A2OLE(""));
//Call method of Server
hr = pShellServer->ShowFileInfo(filebstr, &htmlFileBstr, pathBstr);
::CoUninitialize();
VariantInit(&htmlFile);
htmlFile.vt = VT_BSTR;
htmlFile.bstrVal = htmlFileBstr;
}
在服务器和客户端方法中,调试器将BSTR字符串识别为wchar_t * -arrays。但是服务器方法中字符串“ file”的内容例如是:0x02546e80“㤈榧”。
编码适用于所有设置为“多字节编码(Visual Studio)”的项目(客户端/服务器)。
编辑2:
服务器声明为以下:
HRESULT CShellServerx86::ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathBSTR)
{...
//TODO
}
接口的实现:
class IShellServerx86 : public IUnknown {
public:
virtual HRESULT ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathChar) = 0;
};
...和阶级工厂
CShellServerx86ClassFactory类:public IClassFactory {
上市:
CShellServerx86ClassFactory();
〜CShellServerx86ClassFactory();
//CoClass from Interface (Implementation)
class CShellServerx86 : public IShellServerx86 {
public:
CShellServerx86();
virtual ~CShellServerx86();
//inherited from IUnknown
ULONG STDMETHODCALLTYPE AddRef(void);
ULONG STDMETHODCALLTYPE Release(void);
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv);
HRESULT ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathChar);
protected:
ULONG m_uRefCount;
};
受保护的:
ULONG m_uRefCount;
};
DLL中的GetClass-Method:
//inherited methods from IUnknown
ULONG STDMETHODCALLTYPE AddRef(void);
ULONG STDMETHODCALLTYPE Release(void);
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv);
//inherited methods from IClassFactory
HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter,
REFIID riid, void** ppv);
HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock);
}
最佳答案
首先,您必须检查案例中产生的A2OLE
以及是否适合SysAllocString()
的输入。
然后,您必须实现//TODO
-正确构建out参数的值是被调用方的责任。您将必须执行以下操作:
HRESULT CShellServerx86::ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathBSTR)
{
if( htmlFile == 0 ) {
return E_POINTER;
}
// do useful stuff, generate the string for the htmlFile, then
*htmlFile = SysAllocString( TheStringForHtmlFileParameter );
return S_OK;
}
另外,您在调用方中泄漏了
BSTR
:BSTR htmlFileBstr = ::SysAllocString(A2OLE(""));
//Call method of Server
hr = pShellServer->ShowFileInfo(filebstr, &htmlFileBstr, pathBstr);
由于被调用者将创建新的
BSTR
,因此将丢失作为第二个参数传递的BSTR
。而是将其初始化为空指针:BSTR htmlFileBstr = 0;
//Call method of Server
hr = pShellServer->ShowFileInfo(filebstr, &htmlFileBstr, pathBstr);
同样,您也会泄漏所有
BSTR
,因为完成后您不会调用SysFreeString()
。在您拥有的每个SysFreeString()
上调用BSTR
,或者最好使用包装类,例如ATL::CComBSTR
或_bstr_t
。关于c++ - 进程外COM服务器:BSTR未正确编码,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6983471/