从C ++访问COM接口不通过C#注册的COM服务器 [英] Accessing COM Interface from C++ COM Server that doesn't register via C#

查看:775
本文介绍了从C ++访问COM接口不通过C#注册的COM服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我被要求与已经发货的产品(即COM服务器)集成。与此产品一起提供了一个.tlb文件。我使用 tlbimp 导出tlb到主要程序集,我已经包括在我的C#项目。当我尝试执行我的COM客户端时,我收到没有找到接口错误,因为应用程序从未在注册表中注册其typelib。我试图运行server.exe / RegServer根据MSDN文档。它执行,但似乎不更新或添加任何东西在注册表中。

I've been asked to integrate with an already-shipped product that is a COM server. Along with this product was provided a .tlb file. I've used tlbimp to export the tlb to primary assembly and I've included that in my C# project. When I attempt to execute my COM client I receive "No interface found" errors, because the application never registered its typelib in the registry. I've attempted to run "server.exe /RegServer" per the MSDN docs. It executes but doesn't seem to update or add anything in the registry.

我能够通过强制typelib注册通过 regtlibv12 .exe ,但我已在此网站上读取该可执行文件不一致,可能会被弃用

I was able to get past this problem by forcing the typelib to register via regtlibv12.exe, but I've read on this site that that executable is inconsistent and may be deprecated.

该链接还说,关于regtlibv12.exe:

That link also says, in regards to regtlibv12.exe:


是不注册其类型库的COM服务器的解决方法。与上面类似,但注册类型库是可选的,通常只需要在您的开发机上,而不是在运行服务器的机器上。

it is a workaround for COM servers that don't register their type library. Similar as above, but registering type libraries is optional and typically only required on your dev machine, not on the machine that runs the server.

如果服务器注册是可选项,那么我似乎找不到解决方法。我试过通过System.Runtime.InteropServices手动定义的接口C#类,但它仍然不工作,除非TLB的库项目在注册表中定义。

If server registration is option, then I can't seem to find a way to get around it. I've tried manually defined the interface in C# classes via System.Runtime.InteropServices, but it still doesn't work unless the library items from the TLB are defined in the registry.

所以,有没有办法解决一个COM服务器没有注册(和我没有代码)在C#,没有执行一些应用程序强制TLB注册?

So, is there a way to get around a COM Server that doesn't register (and for which I have no code) in C#, without executing some application to force the TLB to be registered?

编辑:这里是通过 oleview 从TLB导出的IDL。根UUID在注册表的typelib部分中作为主互操作程序集(我假定由于tlbimp调用),但库项本身在任何地方没有任何引用。在注册表中搜索具体类或接口UUID为空。

Here is the IDL I exported from the TLB via oleview. The Root UUID is found in the typelib section of the registry as a Primary Interop Assembly (I assume due to the tlbimp call), but the library items themselves doesn't have any references anywhere. Searching for the Concrete Class or Interface UUID in the registry comes back blank.

        [
      uuid(C8CF03E5-FD1F-11D3-8C03-0080C8D3C5D3),
      version(1.0),
      custom(DE77BA64-517C-11D1-A2DA-0000F8773CE9, 100663657),
      custom(DE77BA63-517C-11D1-A2DA-0000F8773CE9, 1153317527),
      custom(DE77BA65-517C-11D1-A2DA-0000F8773CE9, "Created by MIDL version 6.00.0361 at Wed Jul 19 09:58:45 2006
    ")

    ]
    library EFilm
    {
        // TLib :     // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
        importlib("stdole2.tlb");

        // Forward declare all types defined in this typelib
        dispinterface IEFilm;

        [
          uuid(C8CF03E6-FD1F-11D3-8C03-0080C8D3C5D3)
        ]
        dispinterface IEFilm {
            properties:
            methods:
                [id(0x00000001)]
                VARIANT_BOOL oleOpenStudy(
                                BSTR strPatientID, 
                                BSTR strAccessionNo, 
                                VARIANT_BOOL bCloseCurWindow, 
                                VARIANT_BOOL bAddToWindow, 
                                short nSeriesRows, 
                                short nSeriesCols, 
                                short nImageRows, 
                                short nImageCols, 
                                VARIANT_BOOL bAutoSeriesFormat, 
                                VARIANT_BOOL bAutoImageFormat);
                [id(0x00000002)]
                VARIANT_BOOL oleShowMainWindow(long nCmdShow);
                [id(0x00000003)]
                VARIANT_BOOL oleShowSearchWindow(long nCmdShow);
                [id(0x00000004)]
                VARIANT_BOOL olePositionMainWindow(
                                short left, 
                                short top, 
                                short right, 
                                short bottom);
                [id(0x00000005)]
                VARIANT_BOOL oleSetForegroundWindow();
                [id(0x00000006)]
                VARIANT_BOOL oleOpenSearchRemote(
                                BSTR strPatientID, 
                                BSTR strAccessionNo);
                [id(0x00000007)]
                VARIANT_BOOL oleOpenStudy2(
                                BSTR strPatientID, 
                                BSTR strAccessionNo, 
                                VARIANT_BOOL bCloseCurWindow, 
                                VARIANT_BOOL bAddToWindow, 
                                short nSeriesRows, 
                                short nSeriesCols, 
                                short nImageRows, 
                                short nImageCols, 
                                VARIANT_BOOL bAutoSeriesFormat, 
                                VARIANT_BOOL bAutoImageFormat, 
                                BSTR strImageSource);
                [id(0x00000008)]
                VARIANT_BOOL oleCloseAllWindows();
                [id(0x00000009)]
                VARIANT_BOOL oleCloseCurrentWindow();
                [id(0x0000000a)]
                VARIANT_BOOL oleOpenStudy3(
                                BSTR strPatientID, 
                                BSTR strAccessionNo, 
                                BSTR strStudyInstanceUID, 
                                VARIANT_BOOL bCloseCurWindow, 
                                VARIANT_BOOL bAddToWindow, 
                                short nSeriesRows, 
                                short nSeriesCols, 
                                short nImageRows, 
                                short nImageCols, 
                                VARIANT_BOOL bAutoSeriesFormat, 
                                VARIANT_BOOL bAutoImageFormat, 
                                BSTR strImageSource);
                [id(0x0000000b)]
                VARIANT_BOOL oleSearch(
                                BSTR searchParams, 
                                VARIANT* searchResults, 
                                BSTR lpszImageSource);
                [id(0x0000000c)]
                VARIANT_BOOL oleOpenSearch(
                                BSTR strPatientID, 
                                BSTR strAccessionNo, 
                                BSTR lpszImageSource);
                [id(0x0000000d)]
                VARIANT_BOOL oleLoginViaDomain(
                                BSTR strUsername, 
                                BSTR strPassword, 
                                BSTR strDomainName);
                [id(0x0000000e)]
                VARIANT_BOOL oleLoginViaFusion(
                                BSTR strUsername, 
                                BSTR strPassword, 
                                BSTR strWSDLFile);
                [id(0x0000000f)]
                VARIANT_BOOL oleLoginViaFusionWithToken(
                                BSTR strUsername, 
                                BSTR strToken, 
                                BSTR strWSDLFile);
                [id(0x00000010)]
                VARIANT_BOOL oleSaveCurrentUserProfile();
                [id(0x00000011), helpstring("method oleOpenStudy4")]
                VARIANT_BOOL oleOpenStudy4(
                                BSTR strOpenStudyInfoXML, 
                                VARIANT_BOOL bCloseCurWindow, 
                                VARIANT_BOOL bFindRelatedStudies, 
                                unsigned long nNumPriors, 
                                BSTR strProtocolListXML);
                [id(0x00000012), helpstring("method oleExportAsBitmap")]
                VARIANT_BOOL oleExportAsBitmap(
                                BSTR destinationDirectory, 
                                short bitmapFormat);
                [id(0x00000013), helpstring("method oleLogout")]
                VARIANT_BOOL oleLogout();
                [id(0x00000014), helpstring("method oleOpenStudy5")]
                VARIANT_BOOL oleOpenStudy5(
                                BSTR strOpenStudyInfoXML, 
                                short nRows, 
                                short nCols, 
                                short nImageRows, 
                                short nImageColumns, 
                                VARIANT_BOOL bShowStudyManager, 
                                VARIANT_BOOL bCloseCurWindow, 
                                VARIANT_BOOL bFindRelatedStudies, 
                                unsigned long nNumPriors, 
                                VARIANT_BOOL bApplyHP, 
                                BSTR strProtocolListXML);
                [id(0x00000015), helpstring("method oleLock")]
                VARIANT_BOOL oleLock();
                [id(0x00000016), helpstring("method oleUnlock")]
                VARIANT_BOOL oleUnlock();
                [id(0x00000017), helpstring("method oleIsLocked")]
                VARIANT_BOOL oleIsLocked();
                [id(0x00000018), helpstring("method oleSelectServers")]
                VARIANT_BOOL oleSelectServers(
                                BSTR strImageSourceGUID, 
                                BSTR strServerList);
        };

        [
          uuid(C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3)
        ]
        coclass Document {
            [default] dispinterface IEFilm;
        };
    };

EDIT2:

启动VM并跟踪更改。在初始服务器自注册期间,发生的唯一注册是:

I've loaded up a VM and tracked the changes. During initial server self-registration, the only registration that happens is this:

    [HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}]
@="EFilm Document"

[HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}\AuxUserType]
@=""

[HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}\AuxUserType\2]
@="EFilm"

[HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}\AuxUserType\3]
@="eFilm"

[HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}\DefaultIcon]
@="C:\\PROGRA~1\\MERGEH~1\\eFilm\\eFilm.exe,1"

[HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}\InprocHandler32]
@="ole32.dll"

[HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}\Insertable]
@=""

[HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}\LocalServer32]
@="C:\\PROGRA~1\\MERGEH~1\\eFilm\\eFilm.exe"

[HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}\MiscStatus]
@="32"

[HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}\ProgId]
@="EFilm.Document"

[HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}\verb]
@=""

[HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}\verb\0]
@="&Edit,0,2"

[HKEY_CLASSES_ROOT\CLSID\{C8CF03E4-FD1F-11D3-8C03-0080C8D3C5D3}\verb\1]
@="&Open,0,2"

strong> regtlibv12.exe 它会添加以下注册表项:

When I execute regtlibv12.exe it adds the following registry entries:

    [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\{C8CF03E5-FD1F-11D3-8C03-0080C8D3C5D3}\1.0]
@="EFilm"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\{C8CF03E5-FD1F-11D3-8C03-0080C8D3C5D3}\1.0\FLAGS]
@="0"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\{C8CF03E5-FD1F-11D3-8C03-0080C8D3C5D3}\1.0\0\win32]
@="C:\\eFilm\\eFilm.tlb"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\{C8CF03E5-FD1F-11D3-8C03-0080C8D3C5D3}\1.0\HELPDIR]
@="C:\\eFilm"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{C8CF03E6-FD1F-11D3-8C03-0080C8D3C5D3}]
@="IEFilm"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{C8CF03E6-FD1F-11D3-8C03-0080C8D3C5D3}\ProxyStubClsid]
@="{00020420-0000-0000-C000-000000000046}"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{C8CF03E6-FD1F-11D3-8C03-0080C8D3C5D3}\ProxyStubClsid32]
@="{00020420-0000-0000-C000-000000000046}"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{C8CF03E6-FD1F-11D3-8C03-0080C8D3C5D3}\TypeLib]
@="{C8CF03E5-FD1F-11D3-8C03-0080C8D3C5D3}"
"Version"="1.0"

没有那些我的客户端不运行。技术上它只是HKLM \software \classes \interface行是必需的。即使我不运行 regtlibv12.exe 并手动输入这4行,它将开始运行。所以,有没有办法,我可以使这个工作,而不添加这些行到注册表?

Without those my client does not run. Technically it's just the HKLM\software\classes\interface lines that are required. Even if I don't run regtlibv12.exe and manually enter these 4 lines it will start functioning. So, is there a way I can make this work without adding these lines to the registry?

推荐答案


所以,有没有办法,我可以使这个工作,而不添加这些行到注册表?

So, is there a way I can make this work without adding these lines to the registry?

进程服务器始终要求接口密钥存在。

No, an out-of-process server always requires the Interface keys to be present. Necessary so that Windows can figure out how to serialize the arguments of a method call from the client process to the server process.

使用C ++编写的COM服务器通常需要使用C ++编写的COM服务器,这样可以使得Windows可以找到如何将从客户端进程到服务器进程的方法调用的参数序列化。 不是依赖类型库封送,它通常使用专用的代理/存根DLL。这很容易从IDL生成,midl工具自动生成DLL的源代码。你必须找到该DLL,并使用Regsvr32.exe让它注册自己和编写接口密钥。有很少的面包屑给你找到那个DLL,除非它是小的,可能有ps的文件名。

A COM server that was written in C++ typically does not depend on type library marshaling, it normally uses a dedicated proxy/stub DLL. Which is easy to generate from the IDL, the midl tool auto-generates the source code for the DLL. You'll have to find that DLL and use Regsvr32.exe to get it to register itself and write the Interface keys. There are few breadcrumbs to give you to find that DLL, other than that it will be small and maybe has "ps" in the filename.

使用regtlibv12.exe或写这些密钥本身是一个有效的解决方法。 COM服务器公开的接口实际上与类型库封送处理兼容。它是一个基于IDispatch的简单的后绑定接口,严格使用自动兼容类型,所以你不应该有任何问题。使用专用的代理/存根更快,但是当你使用缓慢的后期绑定时,就没关系了。

Using regtlibv12.exe or writing these keys yourself is otherwise a valid workaround. The interface that the COM server exposes is in fact compatible with type library marshaling. It is a simple late-bound interface based on IDispatch that strictly uses Automation compatible types so you should not have any problem. Using a dedicated proxy/stub is faster but that just doesn't matter anymore when you use slow late-binding.

小心服从这个服务器,它是很古老。很可能你仍然可以得到它的支持,如果你有一个问题。喜欢这个。

Be careful taking a dependency on this server, it is very old. Pretty unlikely you can still get support for it if you have a problem. Like this one.

这篇关于从C ++访问COM接口不通过C#注册的COM服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆