You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从MSI安装程序启动的C#前置应用中获取MSI安装包文件名

获取MSI安装包文件名的可行方案

你的问题很典型——通过父进程msiexec只能拿到进程名,而实际的MSI文件路径其实藏在msiexec的命令行参数里。下面给你两种可靠的实现方式:

方法一:解析msiexec进程的命令行参数

通过WMI获取父进程(msiexec)的完整命令行,从中提取MSI文件路径。修改你的C#代码如下:

using System.Management;
using System.Diagnostics;
using System.Linq;
using System;

public static string GetMsiFilePath()
{
    var currentProcessId = Process.GetCurrentProcess().Id;
    var query = $"SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = {currentProcessId}";
    using (var searcher = new ManagementObjectSearcher("root\\CIMV2", query))
    {
        var result = searcher.Get().Cast<ManagementObject>().FirstOrDefault();
        if (result == null) return null;
        
        var parentProcessId = (uint)result["ParentProcessId"];
        using (var parentProcess = Process.GetProcessById((int)parentProcessId))
        {
            // msiexec的命令行通常格式是: msiexec /i "C:\Path\To\YourInstaller.msi" ...
            var commandLine = parentProcess.StartInfo.Arguments;
            // 先处理带引号的路径(应对路径含空格的情况)
            var msiPathStart = commandLine.IndexOf('"');
            if (msiPathStart != -1)
            {
                var msiPathEnd = commandLine.IndexOf('"', msiPathStart + 1);
                return msiPathEnd > msiPathStart ? commandLine.Substring(msiPathStart + 1, msiPathEnd - msiPathStart - 1) : null;
            }
            // 无引号的情况,找第一个带.msi后缀的参数
            return commandLine.Split(' ')
                .FirstOrDefault(arg => arg.EndsWith(".msi", StringComparison.OrdinalIgnoreCase));
        }
    }
}

注意事项

  • 你的CustomAction设置了Impersonate="no",进程拥有足够权限读取msiexec的命令行信息,无需额外权限配置
  • 代码兼容路径带空格(带引号)和不带空格(无引号)的两种常见场景

方法二:直接将MSI文件名作为参数传递给自定义动作(更推荐)

这其实是最可靠的方案——不需要通过进程链反向获取,而是在CustomAction的ExeCommand里直接把MSI路径传进去。

如果使用WiX构建MSI,你可以通过内置的OriginalDatabase属性获取当前MSI的完整路径,然后传递给Agent_Manager.exe:

<CustomAction Id="EXECUTE_AFTER_FINALIZE" Execute="deferred" Impersonate="no" Return="asyncNoWait" 
              FileKey="Agent_Manager.exe" 
              ExeCommand="--firstinstall &quot;[OriginalDatabase]&quot;" />

然后在你的C#程序里直接读取命令行参数即可:

var args = Environment.GetCommandLineArgs();
var msiFilePath = args.FirstOrDefault(arg => arg.EndsWith(".msi", StringComparison.OrdinalIgnoreCase));

优势

  • 完全规避了进程查询的兼容性问题(比如不同Windows版本的WMI行为差异)
  • 实现逻辑更简单,可靠性更高,无需处理复杂的命令行解析逻辑

内容的提问来源于stack exchange,提问作者iamcootis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 14:12:43