(翻译)LearnVSXNow! #8 插曲-regpkg.exe命令
当我准备去写“创建我们的第一个工具集”系列的下一篇时,我意识到我的注册表已经被我之前创建的示例package给污染了。当我试图卸载这些package以便清理这些垃圾时,我和regpkg.exe程序有了一次亲密的接触。早先我就有计划写这么一篇类似主题的文章(但一直没有写),现在我决定不再拖了,就算我们不得不先暂停一下“创建我们的第一个工具集”系列的编写。
在这篇文章里,你可以看到关于这个命令的我认为非常重要的内容。VS 2008 SDK的文档并没有太多关于regpkg.exe的内容,所以,在这篇文章中我尽量根据我的经验,用容易理解的语言来帮助你了解它。
熟悉一下regpkg.exe
如果看过了前面的文章,并且创建了示例包,你的Visual Studio experimental hive下就注册了一些VSPackage的信息。你的注册表(和VS experimental hive)已经被没有用的package给污染了。为了清理掉这些垃圾,我们将和regpkg.exe来一次“亲密的接触”,利用它来卸载这些package。
任何一个package和它的对象(例如菜单和工具窗)都可以通过VS 2008 SDK(当然也包括VS 2005 SDK)提供的regpkg.exe程序注册并集成到VS IDE中。regpkg.exe程序的作用就是注册和卸载VSPackage,并且支持“手动”地注册和卸载。
用哪个版本的regpgk.exe?
如果你在电脑上同时安装了VS 2005 SDK和VS 2008 SDK,你的机子上就会有两个不同版本的regpkg.exe。每一个只能用在由相应版本的VS SDK创建的package上。如果为了自动找到该程序,你把其中一个regpkg.exe程序所在的路径放到了环境变量Path里,你就有可能遇到由于版本不对而带来的问题。所以,当你的package注册失败时,首先要确定是不是用了错误版本的regpkg.exe程序。
VS 2008 SDK版本的regpkg.exe位于VS 2008 SDK的安装目录(可以参考环境变量VSSDK90Install的值)下的VisualStudioIntegration\Tools\Bin目录中。在该目录下还有一个VS2005的子目录,里面放的值VS 2005 SDK版本的regpkg.exe。
那么,这两个版本的regpkg.exe有什么区别呢?regpkg.exe程序在运行时,会扫描一个程序集中的Package类上面附加的一些Attribute,这些Attribute定义在Microsoft.VisualStudio.Shell.dll程序集(对于VS 2005)或者Microsoft.VisualStudio.Shell.9.0.dll程序集(对于VS 2008)中。这些不同版本的Attribute虽然有相同的名字,但它们并不是同一种类型(因为他们在不同的程序集里),所以regpkg.exe无法扫描到不同版本的Attribute。
你可以试一下:在任意一个VSPackage项目里,删掉对~Shell.9.0.dll的引用,并添加对~Shell.dll的引用。当生成你的VSPackage时,你会看到“No registration data found in this assembly”的错误消息。这个消息出现在成功编译package之后,这是因为改变引用并不会导致编译不通过。出现这个错误的原因,是由于在MSBuild任务里运行了regpkg.exe,而那些注册package需要的attribute又是定义在另外版本的sdk中的,所以会注册不成功。
regpgk.exe可以做什么?
regpkg会扫描程序集中和package注册有关的attribute,并根据这些attribute生成一个注册项的集合,供下一步使用。我们可以在运行regpkg.exe的时候为它指定参数,以实现:
- 把注册信息导出到文件中,供安装程序(msi文件)使用。
- 把注册信息写入注册表——也就是注册我们的package。
- 从注册表中删除注册信息——也就是卸载package。
怎样使用regpgk.exe?
当运行regpkg.exe的时候,你必须告诉它要注册的程序集的名字,以及一些注册的选项(以命令行参数的形式)。regpkg.exe接受如下的命令行语法:
regpkg.exe [options] AssemblyPath
参数AssemblyPath是要注册的程序集的路径,是相对于正在运行regpkg的路径的相对路径(译者注:很不幸,我在使用regpkg时,必须用绝对路径才能够使这个命令正确运行,用相对路径会报错。所以读者在尝试这篇文章里的例子时,如果报错,可以使用绝对路径来试一下。)。 [options]可以指定你希望执行的操作,或者指定注册项的路径。下面的表格列出了可以使用的options:
选项 | 描述 |
/ranu |
如果你登录的账户不是系统管理员,你就应该用这个选项。应用该选项后,注册信息会写到HKEY_CURRENT_USER下。我建议在开发阶段要一直用这个选项。 |
/root:RegRoot |
指定注册表里的一个根目录,在package注册时写入或删除的键都会位于该根目录下。如果没有指定根目录的话,regpkg.exe就会根据package类上面附加的 DefaultRegistryRootAttribute指定的根目录来注册package。(译者注:可以参考第2篇文章里关于DefaultRegistryRoot的内容) 当开发package的时候,我们通常会用Visual Studio实验室模式(Experimental Hive)来测试我们的package,所以我们必须用Software\Microsoft\VisualStudio\9.0Exp作为根。regpkg.exe会把 Configuration项和它的子项添加到我们指定的根下面。 |
/unregister |
利用该选项,可以清除一个package的注册信息。这个选项不能和下面那一行里的任何一个选项同时用。 |
/regfile:FileName |
这些选项都可以使regpkg.exe把注册信息导出到文件里,以便供其他的程序所用(例如安装程序)。前四个选项必须指定一个文件名:即导出后的文件的文件名。你一次只能用其中的一个选项,它们不能同时用。这四个选项分别用于导出reg、rgs、vrg和wix文件。另外,如果你用了/vrgfile选项的话,你还可以再加上/rgm选项,以便再创建一个rgm文件。 如果你想搞清楚regpkg在注册package时会注册什么样的信息进去的话,我建议你可以用/regfile选项:当regpkg.exe执行完之后,可以用记事本来查看它生成的reg文件。通过双击reg文件,也可以把注册信息添加到注册表。 |
/CodeBase |
当注册一个package的时候,包含这个package的程序集也应该被注册,因为在使用package的时候,VS要加载对应的程序集。可以用程序集的全名来注册(通过/Assembly选项),VS会从GAC里加载它;也可以通过绝对路径来注册它(通过/CodeBase选项),VS会从这个路径里加载它。 |
示例
让我们看一下一些使用regpkg的例子。
生成reg文件
这个例子为第2篇文章中的EmptyPackage生成了EmptyPackage.reg文件:
regpkg.exe /regFile:.\EmptyPackage.reg /ranu /root:Software\Microsoft\VisualStudio\9.0Exp .\bin\Debug\EmptyPackage.dll
这条命令运行完后,我们可以在生成的reg文件里看到如下内容:
REGEDIT4
[HKEY_CURRENT_USER\9.0Ex\Configuration\InstalledProducts\EmptyPackagePackage]
@="#110"
"Package"="{223643a0-af7c-4741-99df-e9641691af50}"
"ProductDetails"="#112"
"PID"="1.0"
"LogoID"="#400"
[HKEY_CURRENT_USER\9.0Ex\Configuration\Packages\{223643a0-af7c-4741-99df-e9641691af50}]
@="MyCompany.EmptyPackage.EmptyPackagePackage, EmptyPackage, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
"InprocServer32"="C:\\Windows\\system32\\mscoree.dll"
"Class"="MyCompany.EmptyPackage.EmptyPackagePackage"
"Assembly"="EmptyPackage, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
[HKEY_CURRENT_USER\9.0Ex\Configuration\Packages\{223643a0-af7c-4741-99df-e9641691af50}]
"ID"=dword:00000001
"MinEdition"="Standard"
"ProductVersion"="1.0"
"ProductName"="EmptyPackage"
"CompanyName"="MyCompany"
这个文件包含三个段注册信息,这些信息都会注册到Configuration注册项下面。第一段和第三段的信息来自于EmptyPackagePackage类上面附加的一些attribute:
[InstalledProductRegistration(false, "#110", "#112", "1.0", IconResourceID = 400)]
[ProvideLoadKey("Standard", "1.0", "EmptyPackage", "MyCompany", 1)]
[Guid(GuidList.guidEmptyPackagePkgString)]
public sealed class EmptyPackagePackage : Package { ... }
第二段是关于程序集和package的信息。
注册package
去掉/regfile选项的话,我们的package注册信息就会直接写到注册表里了:
regpkg.exe /ranu /root:Software\Microsoft\VisualStudio\9.0Exp .\bin\Debug\EmptyPackage.dll
我们可以运行regedit.exe打开注册表编辑器,来看一下上面这条命令执行后的结果。
卸载package
我猜你已经开始想象怎样卸载package了。没错,我们只需要简单地在命令行里加上/unregister选项:
regpkg.exe /unregister /ranu /root:Software\Microsoft\VisualStudio\9.0Exp .\bin\Debug\EmptyPackage.dll
如果运行regedit.exe打开注册表编辑器的话,你会看到EmptyPackagePackage相关的注册键已经被删除了。
在开发阶段卸载package
如果我们可以在项目里添加一些可以用来卸载没用的package的东西,是非常棒的。有好几种方法可以做到这一点。我建议你用最简单的方法:在项目里添加一个command文件(.cmd),在这个文件里调用regpkg.exe,并加上/unregister选项。例如:
"%VSSDK90Install%\VisualStudioIntegration\Tools\Bin\regpkg.exe" /unregister /ranu /root:Software\Microsoft\VisualStudio\9.0Exp .\bin\Debug\<your.dll>
pause
我建议在调用regpkg.exe时,用环境变量VSSDK90Install来避免和VS 2005 SDK的regpkg.exe混淆。我假设你是把这个command文件放在了项目文件(csproj)的目录下,如果不是的话,请你修改这个command文件里的dll的路径。
一定要注意,每次编译package后,这package会被重新注册进去。另外,如果你的解决方案下不止一个package项目,我建议把cmd文件放在解决方案文件夹下,以便卸载解决方案下的所有package。
总结
现在我们与regpkg.exe命令有了一次亲密接触了,并且知道它是怎样工作的了。由于VS 2005 SDK和VS 2008 SDK用的是不同的regpkg.exe,所以使用的时候一定要小心,确保使用正确的那个。
用这个命令可以把注册项写入一个文件里,并且在真正注册进去之前检查一下它。这可以帮助我们清楚到底注册了什么东西,甚至可以帮助我们找到package注册时遇到的错误。
另外,我们也可以在项目里添加一个command文件并根据自己的需要来卸载package,这是一个不错的用法。
原文链接:http://dotneteers.net/blogs/divedeeper/archive/2008/01/22/LearnVSXNowPart8.aspx
出处:http://www.cnblogs.com/default
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。