c# - 从未通过 C# 注册的 C++ COM 服务器访问 COM 接口(interface)

标签 c# c++ visual-studio-2012 com

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

我可以通过 regtlibv12.exe 强制类型库注册来解决这个问题,但我有 read on this site that that executable is inconsistent and may be deprecated .

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

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# 类中手动定义接口(interface),但它仍然不起作用,除非 TLB 中的库项在注册表中定义。

那么,有没有办法在不执行某些应用程序强制注册 TLB 的情况下绕过未在 C# 中注册(并且我没有代码)的 COM 服务器?

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

        [
      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;
        };
    };

编辑2:

我已经加载了一个 VM 并跟踪了变化。在初始服务器自注册期间,唯一发生的注册是这样的:

    [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"

当我执行 regtlibv12.exe 时,它会添加以下注册表项:

    [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 行,它也会开始运行。那么,有没有一种方法可以在不将这些行添加到注册表的情况下完成这项工作?

最佳答案

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

不,进程外服务器总是需要接口(interface)键存在。必要的,以便 Windows 可以弄清楚如何序列化从客户端进程到服务器进程的方法调用的参数。

用 C++ 编写的 COM 服务器通常依赖于类型库编码(marshal)处理,它通常使用专用代理/ stub DLL。从 IDL 很容易生成,midl 工具会自动生成 DLL 的源代码。您必须找到该 DLL 并使用 Regsvr32.exe 使其自行注册并编写接口(interface) key 。几乎没有面包屑可以让您找到该 DLL,除此之外它会很小并且文件名中可能有“ps”。

使用 regtlibv12.exe 或自己编写这些 key 是一种有效的解决方法。 COM 服务器公开的接口(interface)实际上与类型库编码(marshal)处理兼容。它是一个基于 IDispatch 的简单后期绑定(bind)接口(interface),严格使用自动化兼容类型,因此您应该没有任何问题。使用专用代理/ stub 更快,但当您使用慢速后期绑定(bind)时,这就不再重要了。

小心依赖这个服务器,它很旧。如果遇到问题,您仍然不太可能获得支持。就像这个。

关于c# - 从未通过 C# 注册的 C++ COM 服务器访问 COM 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21395906/

相关文章:

visual-studio-2012 - 禁用 float 选项卡 visual studio 2012

c# - Expand 在查询中做了什么?

c# - C# 优化器性能差?

c++ - 检查一个程序中是否所有 C++ 函数都抛出异常的工具

VB.NET For each 枚举不正确

C++继承与LNK2019

c# - 找不到与请求 URI 匹配的 HTTP 资源 - Web API + Angular

c# - 如何将自定义控件派生的 TabItem 添加到 WPF 中的 TabControl?

c++ - 在没有 decltype 的情况下声明时,函数定义中 decltype 中的依赖类型或参数无法编译

c# - 双多维数组,在C++中,最好的方法