windows 使用 WiX 生成和安装 Typelib
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/567925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Typelib Generation and Installation with WiX
提问by Robert P
After asking about what Visual Studio does to register a COM Library, it became clear that VS did two things for COM registration:
在询问 Visual Studio 为注册 COM 库做了什么之后,很明显 VS 为 COM 注册做了两件事:
- Registered the COM Library
- Creates and registers a Type Library
- 注册了 COM 库
- 创建并注册类型库
Visual Studio seems to do this registration using regasm.exe. For the first part (the direct COM registration) using tallow
or heat
(WiX 2.0 or WiX 3.0) seems to get all of the basic COM registration information correct.
Visual Studio 似乎使用 regasm.exe 进行此注册。对于第一部分(直接 COM 注册),使用tallow
or heat
(WiX 2.0 或 WiX 3.0)似乎使所有基本的 COM 注册信息都正确。
However, what tallow/heat doesn't seem to do is set up a type library installation. It would be possible to create a custom action to do this with a WiX installer and regasm.exe, but invoking custom actions are not best practices when it comes to Microsoft installer based installers.
但是,tallow/heat 似乎没有做的是设置类型库安装。可以使用 WiX 安装程序和 regasm.exe 创建自定义操作来执行此操作,但是当涉及基于 Microsoft 安装程序的安装程序时,调用自定义操作不是最佳做法。
Upon further research, it looks like an msi has the ability to generate the type library upon installation. In fact, WiX seems to have direct support for it! In a file element, you can add a Typelibelement. In fact, an article over here on wixhas an example of filling out the TypeLib element with Interfaceelements.
经过进一步研究,看起来 msi 能够在安装时生成类型库。事实上,WiX 似乎对它有直接的支持!在文件元素中,您可以添加一个Typelib元素。事实上,这里有一篇关于 wix 的文章有一个使用Interface元素填充 TypeLib 元素的示例。
It seems there's at least two required attributes to an Interface element:
似乎 Interface 元素至少有两个必需的属性:
- Id
- Name
- ID
- 姓名
Larry Osterman speaks about the other parts of the interface that need to be registered for a TypeLib in general, and this Interface entry seems to take care of the individual parts. Larry says we need to specify the ProxyStubClassId32 as "{00020424-0000-0000-C000-000000000046}", so we can easily add that.
Larry Osterman 谈到了一般需要为 TypeLib 注册的接口的其他部分,这个接口条目似乎处理了各个部分。Larry 说我们需要将 ProxyStubClassId32 指定为“{00020424-0000-0000-C000-000000000046}”,因此我们可以轻松添加它。
Where to go from there and what to fill out for the various Interface elements has me stumped. I've gone ahead and added the TypeLib element to my wix file, and it successfully compiles. I'm a bit clueless as to how to set up the Interface elements though. What do we need to do to properly fill out the TypeLib element, and what apps or tools can I use to get it?
从那里去哪里以及为各种界面元素填写什么让我很难过。我已经将 TypeLib 元素添加到我的 wix 文件中,并且它成功编译。不过,我对如何设置界面元素有点无能为力。我们需要做什么才能正确填写 TypeLib 元素,我可以使用哪些应用程序或工具来获取它?
The answer below by wcoenen looks promising...I'm going to give it a shot.
wcoenen 下面的答案看起来很有希望......我要试一试。
Update: Posted my final solution below as an answer.
更新:在下面发布了我的最终解决方案作为答案。
采纳答案by Robert P
Here's the lazy man's way of solving this problem: Use heat
from WiX 3.0.
这是懒人解决这个问题的方法:heat
从 WiX 3.0 开始使用。
If you have a type library generated automatically and installed via regasm, heat
can take the .tlb as an argument in
如果你有一个自动生成并通过 regasm 安装的类型库,heat
可以将 .tlb 作为参数
heat file c:\my\path\to\my.tlb -out tlb.wxs
It will generate all the typelib and interface elements you need to register. This won't solve the problem of needing to know them ahead of time, and it won't solve the problem of GUIDs changing when the version of the assembly changes (even if the interface doesn't - which is the only time you're supposed to change it) but it will get you partway there.
它将生成您需要注册的所有类型库和界面元素。这不会解决需要提前知道它们的问题,也不会解决程序集版本更改时 GUID 更改的问题(即使界面没有更改 - 这是您唯一的一次重新应该改变它)但它会让你中途到达那里。
回答by Wim Coenen
The following trick can help with harvesting any registry changes and turning them into a wxs file, including the typelib element you're after.
以下技巧可以帮助收集任何注册表更改并将它们转换为 wxs 文件,包括您所追求的 typelib 元素。
First, bring your registry back in a state where the type library was not registered:
c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /tlb /u mylib.dll
Export this clean state of the registry to hklm-before.reg:
c:\WINDOWS\system32\reg.exe export HKLM hklm-before.reg
Register the type library again:
c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /tlb mylib.dll
Export the new state of the registry to hklm-after.reg:
c:\WINDOWS\system32\reg.exe export HKLM hklm-after.reg
Now we have two text files, hklm-before.reg and hklm-after.reg. Create a diff.reg filewhich only holds the relevant differences between these. You can find the differences easily with a diffing tool. I like to use the diff tool included in TortoiseSVN since I already use that every day. (WinDiff doesn't seem to work well in this case because of text-encoding issues.)
We can now convert diff.reg into a .wxs by calling
heat.exe
with thereg
command. (Requires wix 3.5 or newer.)heat reg diff.reg -out typelib.wxs
首先,将您的注册表恢复到未注册类型库的状态:
c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /tlb /u mylib.dll
将注册表的这个干净状态导出到 hklm-before.reg:
c:\WINDOWS\system32\reg.exe export HKLM hklm-before.reg
再次注册类型库:
c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /tlb mylib.dll
将注册表的新状态导出到 hklm-after.reg:
c:\WINDOWS\system32\reg.exe export HKLM hklm-after.reg
现在我们有两个文本文件,hklm-before.reg 和 hklm-after.reg。创建一个 diff.reg 文件,该文件仅包含这些之间的相关差异。您可以使用差异工具轻松找到差异。我喜欢使用 TortoiseSVN 中包含的 diff 工具,因为我每天都在使用它。(由于文本编码问题,WinDiff 在这种情况下似乎不能很好地工作。)
现在,我们可以通过调用转换diff.reg成.wxs
heat.exe
与reg
命令。(需要 wix 3.5 或更新版本。)heat reg diff.reg -out typelib.wxs
回答by Robert P
It looks like to register a Type library, the bestway would be to generate your own IDL or ODL file, which will contain your GUIDs. The Typelibs generated directly from the Assembly are [i]dependent[/i] on the assembly version numbers : the GUIDs are generated based on that information, even if the interface hasn't changed. Visual Studio uses regasm to register and generate the typelib. Underneath that, it uses RegisterTypeLib, a win32 call. Using the typelib element seems to do something similar. No good.
看起来像注册一个类型库,最好的方法是生成您自己的 IDL 或 ODL 文件,其中将包含您的 GUID。直接从程序集生成的类型库 [i] 依赖 [/i] 程序集版本号:GUID 是基于该信息生成的,即使接口没有改变。Visual Studio 使用 regasm 注册和生成类型库。在这之下,它使用 RegisterTypeLib,一个 win32 调用。使用 typelib 元素似乎做了类似的事情。不好。
However! Creating the type library by hand is painful. It is possible to get those GUIDs another way: digging them out of the typelib and creating the elements yourself.
然而!手动创建类型库很痛苦。可以通过另一种方式获取这些 GUID:将它们从类型库中挖掘出来并自己创建元素。
Larry Osterman has the information that's needed: there's certain registry keys that need to be set. You can do those with the Registry table (and in Wix3, that means RegistryValue elements.) The trick here is getting the GUIDs: any old GUID will not work. Normally, getting the GUIDs is simply a matter of looking in the IDL for your library (you wrote your own IDL, right? :) ).
Larry Osterman 拥有所需的信息:需要设置某些注册表项。您可以使用 Registry 表(在 Wix3 中,这意味着 RegistryValue 元素)执行这些操作。这里的技巧是获取 GUID:任何旧的 GUID 都不起作用。通常,获取 GUID 只是在 IDL 中查找库的问题(您编写了自己的 IDL,对吗?:))。
If you didn't write an IDL or ODL file to compile into a typelib, they still exist, in the file. Microsoft provides several handy tools: LoadTypeLibExand the ITypeLib interface. With these interfaces, you can browse the type library and get all sorts of information. How do we browse the library?
如果您没有编写 IDL 或 ODL 文件来编译成 typelib,它们仍然存在于文件中。Microsoft 提供了几个方便的工具:LoadTypeLibEx和 ITypeLib 接口。通过这些接口,您可以浏览类型库并获取各种信息。我们如何浏览图书馆?
I simply took a look at how Regasm did it! A quick dissassemble later, and we find that regasm is written in C# too. Glory day. I started up a project, and with a few using statements and a PInvoke later, we have:
我只是看看 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);
Whew! Once we have this out, we have to navigate the structure. This is interacting with unmanaged resources, so get ready to be Marshal
ing stuff around.
哇!一旦我们解决了这个问题,我们就必须浏览结构。这是与非托管资源交互,所以准备好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;
Whew. So, you have to write some code to extract the information. Once you do, you have to fill that information into Registy Entries, as specified By Larry Osterman.
哇。因此,您必须编写一些代码来提取信息。完成后,您必须按照 Larry Osterman 的规定将该信息填写到注册表项中。
Of course, you could avoid that step by simply writing your own IDL file to begin with. The choice in pain: it's up to you!
当然,您可以通过简单地编写自己的 IDL 文件来避免这一步。痛苦中的选择:由您决定!