我有一个在c ++项目中使用的com dll。我没有注册dll但它在同一个解决方案中。我的应用程序不断破坏,我发现它在这里打破了
hr = CoCreateInstance(rclsid, pOuter, dwClsContext, __uuidof(IUnknown), reinterpret_cast<void**>(&pIUnknown));
因为我没有带guid的com类(rclsid)。我做了更多挖掘,我发现它从临时目录中的.tlh文件获取guid,但是guid与我的代码不同。
.tlh文件
struct __declspec(uuid("b10a18c8-7109-3f48-94d9-e48b526fc928"))
DocMapEntry;
// [ default ] interface _DocMapEntry
// interface _Object
// interface IDocMapEntry
c#code(com visable 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创建一个temp .tlh文件? (可选的) 为什么我不能改变这个文件? (可选)
谢谢。
答案 0 :(得分:2)
public interface IDocMapEntry
COM强烈区分CLSID和IID。 IID(接口标识符)标识由COM对象实现的接口。我们可以看到一个,你用[Guid]属性指定它。你将它作为CoCreateInstance()的第四个参数传递,你现在传递IUnknown的IID。
您需要的是CLSID,即类标识符。我们无法在您的代码段中看到它,它是 class 实现您的IDocMapEntry的那个。有一些赔率,它被命名为DocMapEntry。还有额外的赔率,你没有给它[Guid]所以CLR会为你自动生成一个。请注意,修改类时它将更改,这是CoCreateObject()失败的一个可能原因。
忘记用Regasm.exe / codebase注册.NET程序集是另一个原因,你在问题中说了很多。这是必需的,否则COM将无法找到DLL并使调用失败,错误代码为0x80040154,“类未注册”。在相同的解决方案中,不足够,COM搜索规则与.NET使用的规则不同。
另请注意,您正在公开类的内部,通过在类上应用[ClassInterface(ClassInterfaceType.None)]属性来避免这种情况。
答案 1 :(得分:1)
不,您不必注册COM DLL,但您需要注册一个负责创建COM对象的对象。在COM子系统初始化后(通过调用CoRegisterClassObject
或CoInitialize
)调用CoInitializeEx
,在应用程序中执行此操作。
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
,但我怀疑它是你的构建设置中的东西 - 可能是在构建步骤中。
答案 2 :(得分:1)
你的COM对象是否在C#dll中?如果是,您之前是否在您的系统中运行了regasm,这可能已经注册了COM dll。
Guid(“E98676B9-1965-4248-A9B6-74EC5EE5385A”):这是你的界面GUID,而不是你的组件guid。
您应该在实现类中为COM对象声明一个GUID,该对象应该是b10a18c8-7109-3f48-94d9-e48b526fc928。
为什么会用错误的guid创建一个temp .tlh文件?
您确定没有使用#import关键字导入COM dll。