文章目录
debug - 安装.msi时,为所有用户安装程序
概述
为了测试,装了一个test.msi.
安装时,只有安装路径的选择,没有是否为所有用户安装的选项。
本地有2个用户,一个是正式的win10微软账号usr_a,一个是本地开发账号usr_b。
usr_a的权限最高,是本机的第一个管理员账号。usr_b的权限稍微低一些,也是管理员。
如果直接安装test.msi, usr_a可以正常用安装好的test程序。
但是切到usr_b后,无法使用usr_a安装好的test程序。
尝试查看test.msi的命令行帮助,看到有选项可以为所有用户安装。
不过必须在cmd下安装(或者写在.bat中),才能输入命令行参数。
安装.msi时,加了"为所有用户"安装的选项。安装完成后,切到usr_b, 确实可以用test程序了。
笔记
bash
go1.24.1.windows-amd64.msi --help

bash
Windows ® Installer. V 5.0.19041.4651
msiexec /Option <Required Parameter> [Optional Parameter]
安装选项
</package | /i> <Product.msi>
安装或配置产品
/a <Product.msi>
管理安装 - 在网络上安装产品
/j<u|m> <Product.msi> [/t <Transform List>] [/g <Language ID>]
公布产品 - m 公布到所有用户,u 公布到当前用户
</uninstall | /x> <Product.msi | ProductCode>
卸载产品
显示选项
/quiet
安静模式,无用户交互
/passive
无人参与模式 - 只显示进度栏
/q[n|b|r|f]
设置用户界面级别
n - 无用户界面
b - 基本界面
r - 精简界面
f - 完整界面(默认值)
/help
帮助信息
重新启动选项
/norestart
安装完成后不重新启动
/promptrestart
必要时提示用户重新启动
/forcerestart
安装后始终重新启动计算机
日志选项
/l[i|w|e|a|r|u|c|m|o|p|v|x|+|!|*] <LogFile>
i - 状态消息
w - 非致命警告
e - 所有错误消息
a - 操作的启动
r - 操作特定记录
u - 用户请求
c - 初始用户界面参数
m - 内存不足或致命退出信息
o - 磁盘空间不足消息
p - 终端属性
v - 详细输出
x - 额外调试信息
+ - 扩展到现有日志文件
! - 每一行刷新到日志
* - 记录所有信息,除了 v 和 x 选项
/log <LogFile>
与 /l* <LogFile> 相同
更新选项
/update <Update1.msp>[;Update2.msp]
应用更新
/uninstall <PatchCodeGuid>[;Update2.msp] /package <Product.msi | ProductCode>
删除产品的更新
修复选项
/f[p|e|c|m|s|o|d|a|u|v] <Product.msi | ProductCode>
修复产品
p - 仅当文件丢失时
o - 如果文件丢失或安装了更旧的版本(默认值)
e - 如果文件丢失或安装了相同或更旧的版本
d - 如果文件丢失或安装了不同版本
c - 如果文件丢失或较验和与计算的值不匹配
a - 强制重新安装所有文件
u - 所有必要的用户特定注册表项(默认值)
m - 所有必要的计算机特定注册表项(默认值)
s - 所有现有的快捷键方式(默认值)
v - 从源运行并重新缓存本地安装包
设置公共属性
[PROPERTY=PropertyValue]
请查阅 Windows (R) Installer SDK 获得有关
命令行语法的其他文档。
版权所有 (C) Microsoft Corporation. 保留所有权利。
此软件的部分内容系基于 Independent JPEG Group 的工作。
看不大清楚,好像是msiexec + /jm
参数为为所有用户安装。
不过我开始理解错了,没有用msiexec带命令行安装go1.24.1.windows-amd64.msi ,输入成了go1.24.1.windows-amd64.msi /m
不过安装完,所有用户中都可以正常使用安装完的go命令行。
因为我用的/m
参数并不是msiexec的标准参数,但是又有效果,我就想看一下,给msiexec加/m参数会咋样?
bash
msiexec /i "go1.24.1.windows-amd64.msi" /m /log "my_log_2025_0321_1650.txt"
不报错。不知道msiexec是否将/m参数丢弃了。
看日志
bash
Property(S): dirD847BCAADF455EBFA9F73B7D803AC0EF = C:\Program Files\Go\test\wasmmemsize.dir\
Property(S): WixUIRMOption = UseRM
Property(S): WIXUI_INSTALLDIR = INSTALLDIR
Property(S): ALLUSERS = 1 // !!!
Property(S): ARPNOMODIFY = 1
Property(S): ARPINSTALLLOCATION = C:\Program Files\Go\
Property(S): ProgramFiles64Folder = C:\Program Files\
Property(S): TARGETDIR = E:\
Property(S): ProgramMenuFolder = C:\ProgramData\Microsoft\Windows\Start Menu\Programs\
Property(S): EnvironmentEntries = E:\
Property(S): SourceDir = D:\tools\go\
可以看到 ALLUSERS 的值为1,说明 /m
可能是将ALLUSERS置为1了。
查看msiexec用的是哪一个?
bash
D:\tools\go>where msiexec
C:\Windows\System32\msiexec.exe
我现在用的是第2个用户(me),用IDA64看一下, 是否msiexec.exe真有/m
参数。
看到处理 /m 这个参数了,并没有报错,还是继续处理后面的参数。
初步看起来,确实处理这个参数了。
不过汇编看起来不好看啊。
要不用反证法,给一个不存在的参数,看是否报错就行了。
如果能实验出能报错的无效参数,那么就可以反证 /m
参数是有效的。

将 /m
改为/d
, 这是一个不在命令行参数说明中的参数,此时,会弹出msiexec的参数说明界面。这说明/d
参数是无效的。
程序处理参数的方式一般是一致的,既然/m
从单步调试看,是被正常处理的;且不会弹出帮助界面。那么说明/m
是有效的参数。
试试在目标.msi后面直接加参数的测试
bash
go1.24.1.windows-amd64.msi /d

这说明直接在目标msi后面加上参数的效果和在 msiexec后面加的参数是一致的,也说明 /d
这种无效参数,是会弹出msi帮助界面的。
看看目标msi加上/m
参数的效果。
目标msi加/m
参数,是可以正常运行msi的。
这说明,/m
参数虽然没有在msi的标准命令行参数说明中,但是也是一个隐藏正常可用的参数。且根据前面实验的结果(日志中 Property(S): ALLUSERS = 1 // !!!
),/m
参数的作用,就是为所有用户安装程序。
备注
误打误撞实验出来的参数 /m
可以为所有用户安装msi程序。
如果要按照msiexec的标准参数来为所有用户安装,请使用标准的参数
但是我用 /jm
参数会弹出帮助界面啊,并不会安装。
莫非我看错了?
是不是msiexec的命令行参数写错了?
那么用 -m
参数试试,带上日志,看看是否为所有用户安装
bash
go1.24.1.windows-amd64.msi -m /log my_log_go1.24.1.windows-amd64.txt
正常安装完。
查看my_log_go1.24.1.windows-amd64.txt,看看是否有为所有用户安装的选项。
bash
// 写了3个环境变量
WriteEnvironmentStrings: Name: PATH, Value: C:\Program Files\Go\bin, Action 1610612737
WriteEnvironmentStrings: Name: GOPATH, Value: %USERPROFILE%\go, Action 2
WriteEnvironmentStrings: Name: PATH, Value: %USERPROFILE%\go\bin, Action 1073741825
// ...
Property(S): WixUIRMOption = UseRM
Property(S): WIXUI_INSTALLDIR = INSTALLDIR
Property(S): ALLUSERS = 1 // !!! 确实是为所有用户安装了程序
Property(S): ARPNOMODIFY = 1
Property(S): ARPINSTALLLOCATION = C:\Program Files\Go\
Property(S): ProgramFiles64Folder = C:\Program Files\
Property(S): TARGETDIR = E:\
Property(S): ProgramMenuFolder = C:\ProgramData\Microsoft\Windows\Start Menu\Programs\
Property(S): EnvironmentEntries = E:\
Property(S): SourceDir = D:\tools\go\
// ...
Property(S): LogonUser = me // !!! 我是在第2个用户上装的msi
// ...
Property(S): AdminUser = 1 // !!! 第2个用户也是管理员身份
备注
可能是msiexec的命令行帮助写错了。
也有可能是我理解错了。
反正要安装a.msi, 只要加上参数/m
或者-m
就可以为所有用户安装a.msi程序。