Windows安装程序:动态注册表项/值 [英] Windows Setup: Dynamic Registry Keys/Values

查看:226
本文介绍了Windows安装程序:动态注册表项/值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题的简介:

是否有可能使用自己的,自定义变量(可以使用的方式[TARGETDIR ])在VS2010一个Windows安装项目的登记屏幕?具体来说,我需要存储我的程序集的强名称和组装的版本在注册表中,以注册计算机上的COM对象没有安装的用户具有管理员权限。

Is it possible to use your own, custom variables (the way that you can use [TARGETDIR]) in the Registry screen of a Windows Setup project in VS2010? Specifically, I need to store my assembly's strong name and assembly version in the registry, in order to register a COM object on a machine without the installing user having admin rights.

我已经尝试过使用自定义操作,我宁愿不继续这条道路如果可能的话。

I already tried using a custom action, and I'd rather not continue down that road if possible.

下面是具体的,什么我已经试过:

最近,我的雇主开始盲目地从自己的机器中删除所有员工的管理权

Recently, my employer started blindly removing all employees' admin rights from their machines.

我创造,我一直在使用的几个我的工作站,而不再能够进行登记,因为我不再有下HKEY_CLASSES_ROOT适当权限的COM暴露的C#类。

I had created a COM-exposed C# class that I'd been using on a few of my workstations, which is no longer able to be registered, because I no longer have the appropriate permissions under HKEY_CLASSES_ROOT.

通过谷歌搜索,我发现了如何将所有下HKCU *适当的键的注册,但现在我想在我的部署项目来实现这一点。

Through Googling, I found out how to register all of the appropriate keys under HKCU*, but now I'd like to implement this in my deployment project.

我知道如何使用Windows安装程序在注册表中的屏幕,但也有需要存储(安装文件夹,装配强大的名称,版本)自定义键/值。

I understand how to use the Registry screen within Windows Setup, but there are custom keys/values that need to be stored (install folder, assembly strong name, version).

我可以使用自定义操作,但理想情况下,我想Windows安装程序来管理我的注册表设置,因为(a)它的更好,比我在时自动卸载删除所有正确的键/值,(b)在安装,注册表更改是事务性和放大器;回滚在安装时的错误,以及(c)安装/拆卸/交易已经被微软写的,我不会改写它自己的注册表项的逻辑。

I could use a custom action, but ideally, I want Windows Setup to manage my registry settings, because (a) it's better than I am at automatically removing all the proper keys/values upon uninstall, (b) during the install, registry changes are transactional & rolled back upon install error, and (c) the logic for registry key install/removal/transactions is already written by Microsoft, and I won't have to rewrite it myself.

该项目是在VS2008直到今天,但我只是把它升级到VS2010,所以也许有些事情2008年和2010年可能会允许这种行为的改变。

The project was in VS2008 until today, but I just upgraded it to VS2010, so perhaps something has changed between 2008 and 2010 that might allow this behavior.

所以,而不是使用自定义操作,有没有更好的方式来做到这一点。

So, rather than using a custom action, is there a better way to do this?

编辑:我发现的this 答案,这似乎表明,您可以在安装项目中访问Windows安装注册表表。我不知道该怎么做的访问,虽然。在过去,我似乎记得,你可以从一个特殊的外部工具(ORCA)访问MSI的数据库,但我不知道,如果你可以在你的安装项目中访问这些表。

I found this answer, which seems to suggest that you can access the Windows Install "Registry" table within your install project. I'm not sure how to do access it, though. In the past, I seem to recall that you could access the MSI databases from a special external tool (Orca), but I don't know if you can access these tables in your setup project.

编辑2:嗯,我可能将要发生什么;也许是一个生成后事件:

EDIT 2: Ah, I may be on to something; perhaps a post-build event:

  • Use Orca to edit msi from command line?,
  • Examples of Database Queries Using SQL and Script,
  • WiRunSQL.vbs

*运行RegAsm两次 - 一次带/代码库,一次不带;两次与/ REGFILE选项。那么这两个文件合并在一起(删除重复),并更换所有HKCU\Software\Classes HKCR引用。

* Run RegAsm twice - once with /codebase and once without; both times with the /regfile option. Then merge both files together (removing duplicates), and replace all HKCR references with HKCU\Software\Classes.

推荐答案

是的,这是可以做到*。

Yes, this can be done*.

首先,创建将运行作为Windows安装项目的生成后事件的一部分控制台可执行文件。这会修改已经由VS2010建立的MSI文件中的注册

First, create a Console executable that will be run as part of a post-build event of the Windows Setup project. This modifies the Registry table in the MSI file that has been built by VS2010.

请注意:您必须添加一个。提到Microsoft Windows安装程序对象库COM下,对于下面的代码编译

Note: You must add a reference to "Microsoft Windows Installer Object Library" under COM, for the below code to compile.

using System;
using WindowsInstaller;
using System.Runtime.InteropServices;
using System.Reflection;

namespace Post_Setup_Scripting
{
    class Program
    {

        static void Main(string[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine("Incorrect args.");
                return;
            }

            //arg 1 - path to MSI
            string PathToMSI = args[0];
            //arg 2 - path to assembly
            string PathToAssembly = args[1];

            Type InstallerType;
            WindowsInstaller.Installer Installer;
            InstallerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
            Installer = (WindowsInstaller.Installer)Activator.CreateInstance(InstallerType);

            Assembly Assembly = Assembly.LoadFrom(PathToAssembly);
            string AssemblyStrongName = Assembly.GetName().FullName;
            string AssemblyVersion = Assembly.GetName().Version.ToString();

            string SQL = "SELECT `Key`, `Name`, `Value` FROM `Registry`";
            WindowsInstaller.Database Db = Installer.OpenDatabase(PathToMSI, WindowsInstaller.MsiOpenDatabaseMode.msiOpenDatabaseModeDirect);
            WindowsInstaller.View View = Db.OpenView(SQL);
            View.Execute();
            WindowsInstaller.Record Rec = View.Fetch();
            while (Rec != null)
            {
                for (int c = 0; c <= Rec.FieldCount; c++)
                {
                    string Column = Rec.get_StringData(c);
                    Column = Column.Replace("[AssemblyVersion]", AssemblyVersion);
                    Column = Column.Replace("[AssemblyStrongName]", AssemblyStrongName);
                    Rec.set_StringData(c, Column);
                    View.Modify(MsiViewModify.msiViewModifyReplace, Rec);
                    Console.Write("{0}\t", Column);
                    Db.Commit();
                }
                Console.WriteLine();
                Rec = View.Fetch();
            }
            View.Close();

            GC.Collect();
            Marshal.FinalReleaseComObject(Installer);

            Console.ReadLine();
        }
    }
}



变量,我们要在Windows安装程序的注册表屏幕在上面的代码中这些行被替换使用;这可以适用于任何必要的项目

The "variables" that we are going to use in the Windows Setup Registry screen get replaced in these lines of the above code; this could be adapted to any items that are necessary.

string Column = Rec.get_StringData(c);
Column = Column.Replace("[AssemblyVersion]", AssemblyVersion);
Column = Column.Replace("[AssemblyStrongName]", AssemblyStrongName);



二,创建包含要在安装时创建注册表项.reg文件。在上面的代码中,我们通过与装配版本替换的[的AssemblyVersion]所有实例修改,生成后的MSI数据库,和[AssemblyStrongName]与大会的强名称。

Second, create a .reg file that contains the registry keys you want to create upon install. In the code above, we modify the MSI database in the post-build by replacing all instances of [AssemblyVersion] with the assembly version, and [AssemblyStrongName] with the assembly's strong name.

[HKEY_CURRENT_USER\Software\Classes\Record\{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\[AssemblyVersion]]
"Class"="MyClass.MyClass"
"Assembly"="[AssemblyStrongName]"
"RuntimeVersion"="v2.0.50727"
"CodeBase"="[TARGETDIR]MyClass.dll"

三,通过右键单击导入.reg文件到Windows安装程序的注册表屏幕VS2010注册表目标计算机上,然后单击导入。

Third, import the .reg file into the Windows Setup registry screen in VS2010 by right-clicking "Registry On Target Machine", and clicking "Import".

最后,调用生成后的可执行文件中的安装项目的PostBuildEvent属性:

Finally, call the post-build executable in the "PostBuildEvent" property of the setup project:

"C:\Path\To\Exe\Post-Setup Scripting.exe" [Path to MSI] [Path To DLL to extract strong name/version]






*这是不是有点不同使用[TARGETDIR],因为[TARGETDIR]获取在安装时解决,而这些变量,将在构建时得到解决。对于我的解决方案,我需要在编译时间来解决,因为我的版本号与每个构建递增。


* This is a little different than using [TARGETDIR], because [TARGETDIR] gets resolved at install time, and these "variables" will get resolved at build time. For my solution, I needed to resolve at build time, because my version number increments with each build.

这篇关于Windows安装程序:动态注册表项/值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆