进程外COM服务器:BSTR未正确封送 我在Visual Studio 2010中开发了一个C++的OPROC COM服务器,以避免Shellextensions().中的64位vs. 32位问题。
我在IDL文件中描述了如下()所示的接口:进程外COM服务器:BSTR未正确封送 我在Visual Studio 2010中开发了一个C++的OPROC COM服务器,以避免Shellextensions().中的64位vs. 32位问题。,c++,visual-studio-2010,com,ole,C++,Visual Studio 2010,Com,Ole,我在IDL文件中描述了如下()所示的接口: 这个文件为我生成了一个代理/存根DLL,我还注册了该DLL以使用标准封送器方法。 如果我现在打电话 IShellServerx86* pShellServer = NULL; CoCreateInstance(__uuidof(CShellServerx86), NULL, CLSCTX_LOCAL_SERVER, __uuidof(IShellServerx86), (void**)&pShellServ
这个文件为我生成了一个代理/存根DLL,我还注册了该DLL以使用标准封送器方法。
如果我现在打电话
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”,但没有任何改变
我是否忘记了任何设置,或者是否应该尝试其他数据类型进行编组
提前谢谢你的帮助
编辑:
客户机的实现是:
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;
}
服务器方法声明如下:
HRESULT CShellServerx86::ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathBSTR)
{...
//TODO
}
在服务器和客户端方法中,调试器将BSTR字符串识别为wchar\u t*-数组。但是,例如,服务器方法中字符串“file”的内容类似于:0x02546e80㤈榧".
编码适用于所有设置为多字节编码(Visual Studio)的项目(客户端/服务器)
编辑2:
服务器声明如下:
class IShellServerx86 : public IUnknown {
public:
virtual HRESULT ShowFileInfo(BSTR file, BSTR* htmlFile, BSTR pathChar) = 0;
};
接口的实现:
//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;
};
…和类工厂
类CShellServerx86ClassFactory:公共IClassFactory{
公众:
CShellServerx86ClassFactory();
~CShellServerx86ClassFactory()
受保护:
ULONG m_uRefCount;
})
从DLL获取类方法:
STDAPI DllGetClassObject ( REFCLSID rclsid, REFIID riid, void** ppv ) {
if (!::InlineIsEqualGUID(rclsid, __uuidof(CShellServerx86)) ) {
return CLASS_E_CLASSNOTAVAILABLE;
}
*ppv = NULL;
CShellServerx86ClassFactory* pShellServerFac;
pShellServerFac = new CShellServerx86ClassFactory;
if (pShellServerFac == NULL) {
return E_OUTOFMEMORY;
}
pShellServerFac->AddRef();
HRESULT hr = pShellServerFac->QueryInterface(riid, ppv);
pShellServerFac->Release();
return hr;
}首先,您必须检查
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);
另外,由于在完成时没有调用SysFreeString()
,因此仍然会泄漏所有BSTR
s
在每个BSTR
上,您拥有或最好使用像ATL::CComBSTR
或\u BSTR\u t
这样的包装类。BSTR只有一个编码,utf16。您留下了大量获得A2OLE()的机会转换错误,这主要取决于默认代码页。通过记录您如何得出编码问题的结论来改进您的问题。问题最有可能出现在ShowFileInfo()中实现。您能显示分配htmlFile
参数的代码吗?我会完全消除A2OLE/多字节编码的内容。const char*file
在Windows上尤其没有意义;路径是UTF-16。我尝试将项目迁移到UNICODE,但没有任何更改。您好,我检查了A2OLE宏和t客户端的BSTR字符串已正确初始化。我还修改了服务器方法,如您的建议(BSTR*htmlfile)。客户端的方法调用和参数是正确的。但是,当服务器启动该方法时,参数仍然不正确。服务器返回的字符串指针也不正确。只有HRESULT返回值是正确的。我真的很困惑?我添加了类工厂(EDIT2)的实现to可以排除任何实现错误。我当前注意到客户端搜索接口ICallFactory,并返回E_INVALIDARG。是否应实现此接口?另一个问题:“HKCR\CLSID\\InProcServer32”“-标准条目必须指向COM服务器或代理/存根DLL?@Tobias:我严重怀疑代理/存根是否可调试-其中包含大量生成的代码。在您的情况下,您可以使用Automation marshaller—您的接口与Automation兼容,您可以通过在IDL中添加oleautomation
标记并注册typelib来使用Automation代理/存根-
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 htmlFileBstr = ::SysAllocString(A2OLE(""));
//Call method of Server
hr = pShellServer->ShowFileInfo(filebstr, &htmlFileBstr, pathBstr);
BSTR htmlFileBstr = 0;
//Call method of Server
hr = pShellServer->ShowFileInfo(filebstr, &htmlFileBstr, pathBstr);