由于公司限制不受我的控制,我有以下情况:
定义以下接口的COM库(没有CoClass,只是接口):
[ object, uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx), dual, nonextensible, helpstring("IService Interface"), pointer_default(unique) ] IService : IDispatch { HRESULT DoSomething(); } [ object, uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx), dual, nonextensible, helpstring("IProvider Interface"), pointer_default(unique) ] IServiceProvider : IDispatch { HRESULT Init( IDispatch *sink, VARIANT_BOOL * result ); HRESULT GetService( LONG serviceIndicator, IService ** result ); }; [ uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx), version(1.0), ] library ServiceLibrary { importlib("stdole2.tlb"); interface IService; interface IServiceProvider; };
我有一个COM(用W ++编写)实现两个接口并为我们的应用程序提供所述服务.我想一切都很好.
我试图建立一个新的IProvider
,并IService
在.NET(C#).
我为COM库构建了一个Primary Interop程序集,并实现了以下C#:
[ComVisible( true )] [Guid( "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" )] public interface INewService : IService { // adds a couple new properties } [ComVisible( true )] [Guid( "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" )] public class NewService : INewService { // implement interface } [ComVisible( true )] [Guid( "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" )] public interface INewProvider : IServiceProvider { // adds nothing, just implements } [ComVisible( true )] [Guid( "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" )] public class NewProvider : INewProvider { // implement interface }
当我尝试将其放入现有的运行时时,我能够NewProvider
从COM(C++)和QueryInterface
IServiceProvider 创建对象.当我尝试在IServiceProvider上调用方法时,System.ExecutionEngineException
抛出a.
我能找到的另一件事是查看#import创建的.tlh文件,显示遗留的COM IExistingProvider类正确显示它是从IServiceProvider派生的.但是,.NET类显示了IDispatch的基础.我不确定这是一个标志,指示,有用,还有别的.
这可能是名称IServiceProvider的问题.检查您是否尚未导入具有相同名称的接口.
当我使用您的IDL创建COM接口库,然后尝试从其他客户端导入它时,我收到警告:
Warning 65 warning C4192: automatically excluding 'IServiceProvider' while importing type library 'ServiceLibrary.dll'
否则,您可以尝试将其重命名为IServiceProvider2.这就是我所做的,一切正常.我正在使用Visual Studio 2008.
如果此代码在您的计算机上正常运行(它在我的计算机上运行正常),则问题可能出在您的实现中.
IDL:
import "oaidl.idl"; [ object, uuid(9219CC5B-31CC-4868-A1DE-E18300F73C43), dual, nonextensible, helpstring("IService Interface"), pointer_default(unique) ] interface IService : IDispatch { HRESULT DoSomething(void); } [ object, uuid(9219CC5B-31CC-4868-A1DE-E18300F73C44), dual, nonextensible, helpstring("IProvider Interface"), pointer_default(unique) ] interface IServiceProvider2 : IDispatch { HRESULT Init( IDispatch *sink, VARIANT_BOOL * result ); HRESULT GetService( LONG serviceIndicator, IService ** result ); }; [ uuid(9219CC5B-31CC-4868-A1DE-E18300F73C45), version(1.0), ] library ServiceLibrary { importlib("stdole2.tlb"); interface IService; interface IServiceProvider2; };
C#:
using System.Runtime.InteropServices; using System.Windows.Forms; using ServiceLibrary; using IServiceProvider=ServiceLibrary.IServiceProvider2; namespace COMInterfaceTester { [ComVisible(true)] [Guid("2B9D06B9-EB59-435e-B3FF-B891C63108B2")] public interface INewService : IService { string ServiceName { get; } } [ComVisible(true)] [Guid("2B9D06B9-EB59-435e-B3FF-B891C63108B3")] public class NewService : INewService { public string _name; public NewService(string name) { _name = name; } // implement interface #region IService Members public void DoSomething() { MessageBox.Show("NewService.DoSomething"); } #endregion public string ServiceName { get { return _name; } } } [ComVisible(true)] [Guid("2B9D06B9-EB59-435e-B3FF-B891C63108B4")] public interface INewProvider : IServiceProvider { // adds nothing, just implements } [ComVisible(true)] [Guid("2B9D06B9-EB59-435e-B3FF-B891C63108B5")] public class NewProvider : INewProvider { // implement interface public void Init(object sink, ref bool result) { MessageBox.Show("NewProvider.Init"); } public void GetService(int serviceIndicator, ref IService result) { result = new NewService("FooBar"); MessageBox.Show("NewProvider.GetService"); } } }
C++客户端:
#include "stdafx.h" #include#include #import "COMInterfaceTester.tlb" raw_interfaces_only #import "ServiceLibrary.dll" raw_interfaces_only using std::cout; int _tmain(int argc, _TCHAR* argv[]) { CoInitialize(NULL); //Initialize all COM Components COMInterfaceTester::INewProviderPtr pNewProvider(__uuidof(COMInterfaceTester::NewProvider)); ServiceLibrary::IServiceProvider2 *pNewProviderPtr; HRESULT hr = pNewProvider.QueryInterface(__uuidof(ServiceLibrary::IServiceProvider2), (void**)&pNewProviderPtr); if(SUCCEEDED(hr)) { VARIANT_BOOL result = VARIANT_FALSE; int *p = NULL; hr = pNewProviderPtr->Init((IDispatch*)p, &result); if (FAILED(hr)) { cout << "Failed to call Init"; } ServiceLibrary::IService *pService = NULL; hr = pNewProviderPtr->GetService(0, &pService); if (FAILED(hr)) { cout << "Failed to call GetService"; } else { COMInterfaceTester::INewService* pNewService = NULL; hr = pService->QueryInterface(__uuidof(COMInterfaceTester::INewService), (void**)&pNewService); if (SUCCEEDED(hr)) { CComBSTR serviceName; pNewService->get_ServiceName(&serviceName); if (serviceName == "FooBar") { pService->DoSomething(); } else cout << "Unexpected service"; pNewService->Release(); } pService->Release(); } pNewProviderPtr->Release(); } else cout << "Failed to query for IServiceProvider2"; pNewProvider.Release(); CoUninitialize (); //DeInitialize all COM Components }