c++ - 如何在 Visual Basic DLL 和 C++ DLL 之间创建隔离/免注册 COM?

标签 c++ vb.net dll manifest regfreecom

我必须在 C++ DLL 中使用 VB (COM) DLL。 我弄清楚了如何从 C++ DLL 访问 VB (COM) DLL,并且它可以工作。

现在我遇到了一个问题,我必须使用隔离的 COM/免注册 COM,因为我无法在每台必须使用该 DLL 的 PC 上注册该 DLL。

我想出了使用 list 文件来实现这一点,但我无法让它工作,而且我不知道出了什么问题。

我有一个名为 AccConnVB.dll 的 VB DLL,其中包含以下 AccConnVB.manifest 文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
 manifestVersion="1.0">
<assemblyIdentity
        type="win32"
        name="AccConnVB"
        version="1.0.0.0" />
<clrClass
        clsid="{70da7ef0-1549-4b27-9b00-ade5f37aecbe}"
        progid="AccConnVB.AccConnVB"
        threadingModel="Both"
        name="AccConnVB.tables" >
</clrClass>
</assembly>

还有一个名为 AccConn.dll 的 C++ DLL,其中包含以下 AccConn.manifest 文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
  manifestVersion="1.0">
<assemblyIdentity
        type = "win32"
        name = "AccConn"
        version = "1.0.0.0" />
<dependency>
        <dependentAssembly>
                    <assemblyIdentity
                                type="win32"
                                name="AccConnVB"
                                version="1.0.0.0" />
        </dependentAssembly>
</dependency>
</assembly>

我的 C++ DLL #define 位于其 stdafx.h 中的 _WIN32_DCOM#import 是带有 no_namespace< 的 AccConnVB.tlb/.

以下是 C++ DLL 中的方法:

JNIEXPORT jint JNICALL Java_natives_AccessConnection_refreshImportZwei
(JNIEnv *env, jclass jobj, jstring jDatabase){
  jint result;
  CComBSTR database;

  const char* nativeDatabase = env->GetStringUTFChars(jDatabase,0);
  database.Append((LPCSTR) nativeDatabase);

  CoInitializeEx(NULL,COINIT_MULTITHREADED);
  {
      ITablesPtr ptr;
      HRESULT hr = ptr.CreateInstance(__uuidof(tables));
      if (SUCCEEDED(hr))
      {
          result = (jint) ptr->refreshImportZwei(BSTR(database));
      }
  }
  CoUninitialize();
}

我确保注册的 AccConnVB.dll 一切正常,但在未注册的计算机上使用它会失败。

通过在 cmd.exe 中执行 mt.exe 并使用以下行来嵌入 list 文件:mt -manifest H:\AccConnVB.manifest -outputresource:H:\AccConnVB.dll;#1 ,分别用于 AccConn.dll 和 AccConn.manifest。

没有设置任何其他内容,访问 AccConn.dll 时,AccConnVB.dll、AccConn.manifest 和 AccConnVB.manifest 位于同一文件夹中。

我按照演练 here 进行操作并尝试了一些变体,但没有任何效果。

提前非常感谢大家!

附件 1:

AccConn.manifest:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
  manifestVersion="1.0">
<assemblyIdentity
     type = "win32"
    name = "AccConn"
    version = "1.0.0.0" />
<file name="AccConnVB.dll">
<comClass
        clsid="{70da7ef0-1549-4b27-9b00-ade5f37aecbe}" 
    tlbid="{1CA12FB4-4A5C-41FF-A508-DCC6CE0D26CD}"
    progid="AccConnVB.tables" />
<typelib
    tlbid="{1CA12FB4-4A5C-41FF-A508-DCC6CE0D26CD}"
    version="1.0" helpdir="" />
</file>
<dependency>
    <dependentAssembly>
                <assemblyIdentity
                            type="win32"
                            name="AccConnVB"
                            version="1.0.0.0" />
    </dependentAssembly>
</dependency>
</assembly>

AccConnVB.manifest:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
 manifestVersion="1.0">
<assemblyIdentity
    type="win32"
    name="AccConnVB"
    version="1.0.0.0" />
</assembly>

附件2:

OfficeConn.manifest - C++-DLL -(更改名称):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<file name="OfficeConn.dll" hashalg="SHA1">
    <comClass clsid="{2C0D73B5-7AA4-4D17-970D-042804E206B2}" tlbid="{DB27F83B-DD8E-4AD8-A6A3-9232A9C1692C}">
    </comClass>
    <typelib tlbid="{DB27F83B-DD8E-4AD8-A6A3-9232A9C1692C}" version="1.0" helpdir="" flags="HASDISKIMAGE">
    </typelib>
</file>
<comInterfaceExternalProxyStub name="IOffice" iid="{19485BDA-0BAE-3527-8F9B-C90B43746B03}" tlbid="{DB27F83B-DD8E-4AD8-A6A3-9232A9C1692C}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}">
</comInterfaceExternalProxyStub>
<comInterfaceExternalProxyStub name="_offClass" iid="{1FA5D7FC-1CAE-49E0-A99E-B97E8FE3466E}" tlbid="{DB27F83B-DD8E-4AD8-A6A3-9232A9C1692C}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}">
</comInterfaceExternalProxyStub>
</assembly>

OfficeConnVB.manifest - VB-DLL -(更改名称):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="OfficeConnVB" version="1.0.0.0" publicKeyToken="38d072ba2818144d" processorArchitecture="msil">
</assemblyIdentity>
<clrClass clsid="{2c0d73b5-7aa4-4d17-970d-042804e206b2}" progid="OfficeConnVB.offClass" threadingModel="Both" name="OfficeConnVB.offClass" runtimeVersion="">
</clrClass>
<clrSurrogate clsid="{453B8C28-201B-3705-8CF1-C492C7B259EA}" name="Microsoft.Office.Interop.Outlook.OlDefaultFolders">
</clrSurrogate>
<clrSurrogate clsid="{B5181856-6837-3E65-AF7B-5020DD408339}" name="Microsoft.Office.Interop.Outlook.OlItemType">
</clrSurrogate>
<clrSurrogate clsid="{ECE70AEA-B928-3392-AE59-01373B29D3DA}" name="Microsoft.Office.Interop.Outlook.OlImportance">
</clrSurrogate>
<clrSurrogate clsid="{D74B5B88-8D75-3D21-A9BA-F6DBDC905F75}" name="Microsoft.Office.Interop.Word.WdSaveOptions">
</clrSurrogate>
<file name="OfficeConnVB.dll" hashalg="SHA1">
</file>
</assembly>

最佳答案

您犯了一个奇怪的常见错误,期望 Windows 能够解决先有鸡还是先有蛋的问题。简单介绍一下 list 的工作方式可能会有所帮助。

Windows 在加载可执行文件时加载 list 内容,条目会添加到内部查找表中。每当应用程序首次请求创建 COM 对象时,底层调用是提供 CLSID guid 的 CoCreateInstance(),它首先查阅该查找表。如果 CLSID 匹配,则该条目告诉它必须加载哪个 DLL。如果没有匹配,则返回到传统的注册表查找。

先有鸡还是先有蛋的问题是您的 DLL 尚未加载。因此它的 list 条目尚未激活。

先有蛋,<clrClass>条目需要进入您嵌入 C++ 可执行文件中的 list 。像这样:

  <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity type="win32" name="AccConn" version="1.0.0.0" />
    <file name="foobar.dll"/>
    <clrClass ...etc>
    </clrClass>
  </assembly>

MSDN 文章 is here .

关于c++ - 如何在 Visual Basic DLL 和 C++ DLL 之间创建隔离/免注册 COM?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27944427/

相关文章:

c++ - 记住创建空白 win32 窗口的所有内容很重要吗

c++ - 为什么这个双重互斥锁不会造成死锁呢?

wpf - 共享 ViewModel 的属性

c++ - 为外部 dll 上的缓冲区分配内存并在主应用程序上使用它是否安全?

c++ - 为什么这个循环不起作用?

c++ - 高斯模糊图像处理c++

c# - 什么架构使用 system.runtime.serialization.ISerializable?

wpf - WPF XAML 中的 My.Resources?

c++ - 在注入(inject)的 DLL 中调用函数?

c++ - 32 位程序无法捕获在 32 位进程上进行的击键,但能够捕获在 64 位进程上进行的击键