VS的安装项目:解决安装后注册表中程序信息InstallLocation为空的问题

  发现此问题是由于我想要得到某个安装好的程序的安装路径,网上搜索后发现程序安装时会把详细安装信息记录在注册表中,HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\,里面的子项有些用名称标志,有些就是以ProductCode标志,

如图中我自己的程序安装后就是通过ProductCode标志的,里面存了有关程序的各种信息,但是我想要的InstallLocation却是个空值,原因是用VS自带的安装项目安装时需要做额外的操作才能把安装路径写入到InstallLocation里。

  网上捣鼓半天,发现共有两种方法,一种是自己写个自定义操作的类库,加入到安装项目里,自己用程序记录下安装路径然后写入注册表,另一种方式麻烦点,但是更可靠,就是用微软提供的工具直接修改安装项目生成后的msi文件。

  第一种方法在一个国外的人的博客上写得比较完整,点此查看,我在这就翻译+详细解释下。安装项目可以添加自定义操作,如果你不熟悉这个网上资料很多,简要说明过程,新建一个类库项目,举例SetEnvironment,把自动生成的class1.cs删掉,往项目中添加新建项,选择安装程序类,编辑新加的安装程序类的代码,加入如下代码

public override void Install(IDictionary stateSaver)
{
    base.Install(stateSaver);

    stateSaver.Add("TargetDir", Context.Parameters["targetdir"].ToString());
    stateSaver.Add("ProductID", Context.Parameters["ProductID"].ToString());
}

public override void Commit(IDictionary savedState)
{
    base.Commit(savedState);

    string productId = savedState["ProductID"].ToString();
    RegistryKey applicationRegistry = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" + productId, true);

    if (applicationRegistry != null)
    {
        applicationRegistry.SetValue("InstallLocation", savedState["TargetDir"].ToString());
        applicationRegistry.Close();
    }
}

  然后生成该项目,右键安装项目——>添加项目输出,选择刚才新建的类库项目,然后右键安装项目——>视图——>自定义操作,进入安装项目的自定义操作界面,在安装和提交两步均加入自定义操作,选择刚才新加的项目输出作为自定义操作,添加后选中安装下面的自定义操作右键点击,打开属性窗口,往CustomActionData填入如下数据:/targetdir="[TARGETDIR]\" /ProductID="[ProductCode]",如下图所示:

这个就是为了把安装路径和ProductCode传入到程序中,具体就是传入到Context.Parameters["targetdir"]和Context.Parameters["ProductID"]中,代码中重写的两个方法会分别在安装和提交时被调用,安装路径是作为InstallLocation的值写入,ProductCode则是为了在注册表中找到本程序对应的项,弄完这些,重新生成安装项目再安装,注册表中的InstallLocation就会有值了。

  第二种方法。首先安装微软提供的工具Orca,是一个可以编辑msi文件的工具,安装文件在windows的sdk安装目录下,我的是win7,就是在C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin目录下,安装好后,先把项目中的安装项目成功生成一次,用Orca打开生成的msi文件,打开后进行如下几步:

  1. 选择菜单中的Transform——>New Transform
  2. 选中Orca界面左侧列表的CustomAction,右边出现相应的表,在表中右键——>Add Row,在各项属性中对应填入Action:SetLocation;Type:51; Source:ARPINSTALLLOCATION;Target:[TARGETDIR]
  3. 选中Orca界面左侧列表的 InstallExecuteSequence,右边出现相应的表,在表中右键——>Add Row,在各项属性中对应填入Action:SetLocation;Condition:ARPINSTALLLOCATION="";Sequence:798。Condition那一项也可以空着不填。
  4. 选择菜单中的Transform——>Generate Transform然后保存mst文件。
  5. 使用命令行用MsiTran.exe来应用转换,该工具也在windows sdk中,命令行基本格式是MsiTran -a "你的mst文件路径" "你的msi文件的路径",当然要切换到MsiTran.exe所在目录下,拿我自己的举个例子如图所示:

  执行成功后再运行安装程序注册表中的InstallLocation项也会有值了。为了不至于每次生成安装项目都手动配置下msi文件,我们可以将命令放到PostBuildEvent里去,进入到安装项目的属性窗口,找到PostBuildEvent项,点击右边小按钮,进入到编辑窗口,加入如下代码:"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\MsiTran" -a "$(ProjectDir)setLocation.mst" "$(BuiltOuputPath)"。第一个""内的内容要根据MsiTran.exe的路径进行调整,我写的是我电脑上的MsiTran.exe文件的路径,命令行格式说明在前面已经说了,只不过这个有些路径用宏来代替了,这个需要把mst文件拷贝到相应位置,在这就是安装项目目录,msi文件在默认的生成路径下,$(ProjectDir)和$(BuiltOutputPath)的内容可以点击PostBuildEvent的编辑窗口右下角的宏按钮来查看。

这样一来每次生成安装项目成功后就会执行命令对msi文件进行配置,就不用每次都手动用命令行来配置了。不过这样每次生成安装项目时会报一个错,"PostBuildEvent"失败,错误代码为"1",'未指定的错误',不过不影响项目的生成,msi文件还是会成功生成,并且可以顺利安装,应该可以指定参数来屏蔽这个无关紧要的错误,可以看看这,我弄了一会儿没弄出来也没深钻了。

  两种方法都可以让注册表中的InstallLocation项目写入正确的值,但个人感觉第二种方式更规范一点,第一种方式仅仅是自己去改了注册表,但是程序安装却不一定是只修改注册表,没准还要把安装路径写到别的地方。参考网上代码我写了一个查找指定名称程序的详细安装信息的代码。

private void ShowSoftware()
        {
            ManagementObjectSearcher MyWMIQuery = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
            ManagementObjectCollection MyWMIQueryCollection = MyWMIQuery.Get();
            foreach (ManagementObject MyMO in MyWMIQueryCollection)
            {
                if (MyMO["Name"].ToString() == "NXADMS")//NXADMS是我的程序名,你若想执行这代码需改成你的程序名
                {
                    PropertyDataCollection properties = MyMO.Properties;
                    foreach (PropertyData property in properties)
                    {

                        dataGridView1.Rows.Add(property.Name, (MyMO[property.Name] == null ? " " : MyMO[property.Name].ToString()));
                    }

                }
            }
            MyWMIQueryCollection = null;
            MyWMIQuery = null;
        }

  执行这段代码也会把一堆东西显示出来,如下图:

也有InstallLocation项,经过我的测试,这个貌似跟上述注册表中的InstallLocation无关,所以第一种方法完成后,这段代码得到的InstallLocation仍然为空,而第二种方法完成这个InstallLocation也会有值!

转载于:https://www.cnblogs.com/ValiancyHe/archive/2012/11/13/2767758.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值