You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Visual Studio引导程序中获取MSI安装项目的内置安装目录

如何在Visual Studio引导程序中获取MSI安装项目的内置安装目录

我之前在做VS安装项目的引导程序时,也碰到过一模一样的问题——明明设置了DefaultLocation,但实际安装路径偶尔会有偏差,想在引导程序里启动刚装的软件,总怕找错地方。给你几个亲测有效的办法,不用怕路径不准,也不用傻乎乎搜整个AppData:

方法一:用后期生成事件保留ARPINSTALLLOCATION设置

你之前改ARPINSTALLLOCATION被VS重建删除的问题,其实可以用后期生成事件自动把这个设置加回去,每次编译后自动生效,不会丢。具体步骤:

  1. 打开你的VS安装项目(.vdproj)的属性页
  2. 找到生成事件 -> 后期生成事件命令行
  3. 输入一段PowerShell脚本,自动修改vdproj文件:
(Get-Content "$(ProjectDir)$(ProjectName).vdproj") -replace '("ARPINSTALLLOCATION" = "8:.*")', '"ARPINSTALLLOCATION" = "8:[INSTALLDIR]"' | Set-Content "$(ProjectDir)$(ProjectName).vdproj"

这个脚本会在每次编译完成后,自动把ARPINSTALLLOCATION绑定到[INSTALLDIR]。之后引导程序就能通过注册表拿到安装路径:

  • 每机器安装:去HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\[你的产品ProductCode]下找InstallLocation
  • 每用户安装:去HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\[你的产品ProductCode]下找对应键

方法二:直接读取MSI数据库里的INSTALLDIR属性

MSI本质是个数据库文件,你可以在引导程序里直接读取它的Property表,拿到内置的INSTALLDIR值,这是最准确的,完全不受用户修改安装路径的影响。比如用C#结合Windows Installer相关API实现:

  1. 引用Microsoft.Deployment.WindowsInstaller库(VS环境一般默认支持)
  2. 用以下代码读取MSI的内置安装目录:
using (var database = new Database("你的MSI文件路径", DatabaseOpenMode.ReadOnly))
{
    var view = database.OpenView("SELECT Value FROM Property WHERE Property = 'INSTALLDIR'");
    view.Execute();
    var record = view.Fetch();
    if (record != null)
    {
        string installDir = record.GetString(1);
        // 这里拿到的就是MSI实际使用的安装目录
    }
}

方法三:在安装项目里手动加注册表项存安装路径

如果不想搞脚本或者读MSI数据库,还有个更简单的办法:在VS安装项目里手动加一个注册表项,把[INSTALLDIR]存进去,引导程序直接读注册表就行:

  1. 打开你的VS安装项目,右键添加注册表项
  2. 选择一个合适的路径,比如HKCU\Software\[Manufacturer]\[ProductName](对应你项目属性里的制造商和产品名)
  3. 新建一个字符串值,比如叫InstallPath,把它的设为[INSTALLDIR]
  4. 保存项目,这个设置不会被VS重建删除,因为是你手动添加的自定义项
    之后引导程序只要去这个注册表路径读InstallPath,就能拿到准确的安装目录了。

方法四:用Windows Installer API直接查已安装产品的路径

如果你的引导程序是在MSI安装完成后才需要路径,那可以用Windows Installer的MsiGetProductInfo函数,直接通过产品的ProductCode查询安装位置:
比如在C#里可以这么调用(需要引用msi.dll):

[DllImport("msi.dll", CharSet = CharSet.Unicode)]
static extern uint MsiGetProductInfo(string productCode, string property, StringBuilder valueBuf, ref int valueBufSize);

// 调用示例
string productCode = "你的MSI产品的ProductCode";
StringBuilder pathBuf = new StringBuilder(1024);
int bufSize = pathBuf.Capacity;
MsiGetProductInfo(productCode, "InstallLocation", pathBuf, ref bufSize);
string installDir = pathBuf.ToString().TrimEnd('\0');

这个方法读的是系统里已安装产品的真实信息,完全准确,不会有偏差。

最后说一句,你担心DefaultLocation不准是对的——用户在安装时完全可以手动修改路径,所以DefaultLocation只是默认值,实际安装路径肯定以MSI的INSTALLDIR为准。上面这几个方法都能拿到真实的内置路径,不用去搜整个AppData文件夹,效率和准确性都高多了。

火山引擎 最新活动