它看起来像注册一个类型库,最好的方法是生成您自己的 IDL 或 ODL 文件,其中将包含您的 GUID。直接从程序集生成的类型库 [i] 依赖于[/i] 程序集版本号:GUID 是基于该信息生成的,即使接口没有更改。Visual Studio 使用 regasm 注册和生成类型库。在此之下,它使用了一个 Win32 调用 RegisterTypeLib。使用 typelib 元素似乎做了类似的事情。不好。
然而!手动创建类型库很痛苦。可以通过另一种方式获得这些 GUID:将它们从类型库中挖掘出来并自己创建元素。
Larry Osterman 拥有所需的信息:需要设置某些注册表项。您可以使用 Registry 表执行这些操作(在 Wix3 中,这意味着 RegistryValue 元素。)这里的技巧是获取 GUID:任何旧的 GUID 都不起作用。通常,获取 GUID 只需查看库的 IDL(您编写了自己的 IDL,对吗?:))。
如果您没有编写 IDL 或 ODL 文件来编译到类型库中,它们仍然存在于文件中。Microsoft 提供了几个方便的工具:LoadTypeLibEx和 ITypeLib 接口。通过这些接口,您可以浏览类型库并获取各种信息。我们如何浏览图书馆?
我只是看看 Regasm 是如何做到的!稍后快速反汇编,我们发现 regasm 也是用 C# 编写的。荣耀日。我启动了一个项目,稍后使用一些 using 语句和一个 PInvoke,我们有:
using System.Runtime.InteropServices; // for struct marshaling
using System.Runtime.InteropServices.ComTypes; // for the ITypeLib + related types
// TYPELIBATTR lives in two places: Interop and ComTypes, but the one
// in Interop is deprecated.
using TYPELIBATTR = System.Runtime.InteropServices.ComTypes.TYPELIBATTR;
/// <summary>
/// The registry kind enumeration for LoadTypeLibEx. This must be made
/// here, since it doesn't exist anywhere else in C# afaik. This is found
/// here: http://msdn.microsoft.com/en-us/library/ms221159.aspx
/// </summary>
enum REGKIND
{
REGKIND_DEFAULT,
REGKIND_REGISTER,
REGKIND_NONE
}
// and this is how we get the library.
[DllImport("oleaut32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
private static extern void LoadTypeLibEx(string strTypeLibName, REGKIND regKind, out ITypeLib TypeLib);
哇!一旦我们有了这个,我们必须导航结构。这是与非托管资源的交互,所以准备好Marshal
周围的东西。
ITypeLib lib = null;
LoadTypeLibEx(Value, REGKIND.REGKIND_NONE, out lib);
IntPtr libInfoPtr = IntPtr.Zero;
lib.GetLibAttr(out libInfoPtr);
TYPELIBATTR libInfo =
(TYPELIBATTR) Marshal.PtrToStructure(libInfoPtr, typeof(TYPELIBATTR));
int typeCount = lib.GetTypeInfoCount();
for (int i = 0; i < typeCount; ++i)
{
ITypeInfo info;
lib.GetTypeInfo(i, out info);
IntPtr typeDescrPtr = IntPtr.Zero;
info.GetTypeAttr(out typeDescrPtr);
TYPELIBATTR type =
(TYPELIBATTR)Marshal.PtrToStructure(typeDescrPtr, typeof(TYPELIBATTR));
// get GUID, other info from the specific type
}
lib.ReleaseTLibAttr(libInfoPtr);
libInfoPtr = IntPtr.Zero;
唷。因此,您必须编写一些代码来提取信息。完成后,您必须按照 Larry Osterman的规定将该信息填写到 Registy Entries 中。
当然,您可以通过简单地编写自己的 IDL 文件来避免该步骤。痛苦中的选择:由你决定!