【问题标题】:c++ application cannot find com dll because compiler generating .tlh file with incorrect guidsc++ 应用程序找不到 com dll,因为编译器生成 .tlh 文件的 guid 不正确
【发布时间】:2013-07-02 17:16:59
【问题描述】:

我有一个在 c++ 项目中使用的 com dll。我没有注册 dll,但它在同一个解决方案中。我的应用程序不断中断,我发现它在这里中断了

hr = CoCreateInstance(rclsid, pOuter, dwClsContext, __uuidof(IUnknown), reinterpret_cast<void**>(&pIUnknown));

因为我没有具有该 guid (rclsid) 的 com 类。我做了更多的挖掘,发现它从临时目录中的 .tlh 文件中获取 guid,但 guid 与我的代码不同。

.tlh 文件

    struct __declspec(uuid("b10a18c8-7109-3f48-94d9-e48b526fc928"))
    DocMapEntry;
    // [ default ] interface _DocMapEntry
    // interface _Object
    // interface IDocMapEntry

c#代码(comvisable dll)

    [ComVisible(true)]
    [Guid("E98676B9-1965-4248-A9B6-74EC5EE5385A")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IDocMapEntry
    {
        int Offset { get; set; }
        int PageOffset { get; set; }
        int PageNumber { get; set; }
    }

我尝试将值更改为正确的值,但它不断更改,Visual Studio 要求我重新加载。

当我使用 com explorer 查看课程时,我得到了一个不同的 clsid,当我尝试取消注册它时,它成功完成,但项目仍然存在并且文件位置是 mscoree。

我的 c++ 应用程序使用 .tlh 文件中的 guid,但没有找到该文件。

public class DocMapEntry : IDocMapEntry
 {
   ...
 }

我的问题是。

我需要注册我的 com dll 才能使用吗? 如何设置课程的指导? 为什么它会创建一个带有错误 guid 的临时 .tlh 文件? (选修的) 为什么我不能更改此文件? (可选)

谢谢。

【问题讨论】:

    标签: c++ visual-studio-2008 com


    【解决方案1】:
     public interface IDocMapEntry
    

    COM 强烈区分 CLSID 和 IID。 IID,接口标识符,标识由 COM 对象实现的接口。我们可以看到,您使用 [Guid] 属性指定了它。您可以将它作为 CoCreateInstance() 的第四个参数传递,您现在可以在其中传递 IUnknown 的 IID。

    您需要的是 CLSID,即类标识符。我们在您的 sn-p 中看不到它,它是任何 class 实现您的 IDocMapEntry 的那个。有可能它被命名为 DocMapEntry。还有额外的几率,你没有给它一个 [Guid],所以 CLR 会为你自动生成一个。请注意,当您修改类时,它会更改,这可能是 CoCreateObject() 失败的原因之一。

    忘记使用 Regasm.exe /codebase 注册 .NET 程序集是另一个原因,您在问题中也说了这么多。这是必需的,否则 COM 将无法找到 DLL 并导致调用失败,错误代码为 0x80040154,“类未注册”。将它放在同一个解决方案中不够,COM 搜索规则与 .NET 使用的规则不同。

    还请注意,您正在公开类的内部,通过在类上应用 [ClassInterface(ClassInterfaceType.None)] 属性来避免这种情况。

    【讨论】:

    • 您好,我在问题中添加了类签名。如何为班级设置 clsid?
    • 具有 [Guid] 属性,就像您为界面所做的那样。就像我在答案中提到的那样。而且您在 C++ 代码中也使用了 __uuidof(),因此使用 [Guid] 实际上并不重要。
    • 我将 guid 属性添加到我的类签名中并且它可以工作。我将 guid 设置为 .tlh 文件中的值
    【解决方案2】:

    不,您不必注册 COM DLL,但您需要注册一个负责创建 COM 对象的对象。在 COM 子系统初始化后(通过调用 CoInitialize 或 CoInitializeEx)调用 CoRegisterClassObject 在您的应用程序中执行此操作。

    IClassFactory *factory = new ObjectFactory();
    
    // Register the factory responsible for creating our COM objects
    DWORD classToken;
    HRESULT hr = CoRegisterClassObject(
        Object_CLSIID,
        factory,
        CLSCTX_LOCAL_SERVER,
        REGCLS_MULTIPLEUSE,
        &classToken);
    
    // Now we can create the objects
    Object *obj = nullptr;
    hr = CoCreateInstance(
        Object_CLSIID,
        nullptr,
        CLSCTX_LOCAL_SERVER,
        Object_IID,
        reinterpret_cast<void**>(&obj));
    

    不知道为什么它会创建一个临时的.tlh,但我怀疑它在你的构建设置中 - 可能在构建步骤中。

    【讨论】:

      【解决方案3】:

      您的 COM 对象是否在 C# dll 中?如果是,您之前是否在系统中运行过 regasm,这可能已经注册了 COM dll。

      Guid("E98676B9-1965-4248-A9B6-74EC5EE5385A"):这是您的界面 GUID,而不是您的组件 GUID。

      您应该在实现类中为 COM 对象声明一个 GUID,它应该是 b10a18c8-7109-3f48-94d9-e48b526fc928。

      为什么会创建一个带有错误 guid 的临时 .tlh 文件?

      您确定没有使用#import 关键字导入 COM dll。

      【讨论】:

      • 如果我注册了 dll 我该如何调试它?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-10
      • 2014-07-16
      • 2021-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多