debug - 安装.msi时,为所有用户安装程序

文章目录

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程序。

END

相关推荐
Ciderw4 个月前
多处理器一致协议(MSI)协议详细介绍
缓存·存储·一致性·msi
马志武5 个月前
win11安装不了msi文件解决办法
win11·msi
几度热忱9 个月前
【win11】Mouse without Borders安装问题&以管理员权限安装msi文件
msi·无界鼠标