msiexec MsiSetExternalUI 的外部处理程序

2024-02-25

早上好,

我希望为 msiexec 实现一个外部处理程序,但不能阻止 msiexec 执行任何不同的操作。我希望能够利用 MsiSetExternalUI 拦截所有消息,但仍然对最终用户具有相同的响应和对话框。

我的主要目标是拦截安装 msi 的缓存源并将其移动到另一个位置。

我尝试过使用日志记录注册表项,但是包的源位置可能会被删除,并且当我截获日志文件并获取 msi 的位置时,包的源将不存在。

例如,在安装exe中嵌入msi,尤其是旧的C++可再发行组件,使用redist将其自身解压到主驱动器根目录上的随机目录并安装,然后在完成后删除该目录。 msiexec 的行为不一致,因为大多数包都缓存在 Windows 安装程序目录 c:\windows\installer 中,而原始包缓存在 c:\programdata\cached 包中。

为什么有些包会被缓存,而另一些则不会?

因此,我想使用外部用户界面,但要确保行为保持不变。

我目前正在测试一个项目

MsiInterop.MsiSetExternalUI(新 MsiInstallUIHandler(_OnExternalUI), MsiInstallLogMode.ExternalUI、IntPtr.Zero);

任何想法或例子都会非常有帮助。


"Intent"

我们在部署中遇到一些问题,人们告诉我们这些问题是什么doing,但不是它们是什么打算. 有时这会导致我们写出详尽的答案,但无法回答问题。我希望这里的情况不是这样。

尝试回答

您想要找到安装期间缓存的 MSI 的确切路径,如下所示:%SystemRoot%\Installer在安装 MSI 期间?

我从来没有尝试过,但是萨沙·博蒙特很久以前发布了一个VBScript,它似乎尝试做你想做的事情(尽管不是在安装过程中):WiX 自定义操作 - MSI 复制自身 https://stackoverflow.com/questions/11470760/wix-custom-action-msi-copy-itself。我从未尝试过这个脚本,也不想推荐它。

关于 C++ redist 的东西:我不确定他们到底在做什么,但微软倾向于一直重写他们自己的规则,他们做了一些事情 - 有时 - 分析时毫无意义。我不会花太多时间去理解它——除非你绝对必须这么做。只是我的2分钱。


我们可以问一个显而易见的问题吗:你为什么需要这份副本? 也许有更好的方法来实现你想要的?下面是用于缓存 MSI 文件的不同文件夹的简要概述以及一些包含 MsiSetExternalUI 信息的链接。


MsiSetExternalUI

我不明白您需要如何像您尝试的那样访问日志MsiSetExternalUI来实现 MSI 文件缓存,但这里有一些使用链接:

  • 使用 MsiSetExternalUI 进行日志记录和过滤 https://serverfault.com/a/615256/20599(serverfault.com)。
  • 包装 Windows Installer 2.0 API http://www.codeproject.com/KB/cs/msiinterop.aspx.
  • 使用 MsiSetExternalUI 处理进度消息 https://msdn.microsoft.com/en-us/library/aa368786(v=vs.85).aspx.

有关 MSI 缓存的更多信息

MSI 缓存的几种形式- 一些内置于 Windows Installer 中,另一些由第三方工具实现,某些 Microsoft 工具有自己的部署方式(例如视觉工作室).

以下是有关如何在系统上缓存 MSI 文件的一些提示。这绝不是完整的,但这是我可以写下的:

1. Windows Installer (msiexec.exe) 缓存

有一个内置的 Windows Installer 功能可以在安装过程中缓存原始 MSI 安装数据库的副本。该缓存副本过去被删除了内部 CAB 文件(使它们比原始文件小得多),但是这在 Windows 7 周围发生了变化,MSI 副本现在以全尺寸缓存 https://stackoverflow.com/questions/208530/why-does-msi-require-the-original-msi-file-to-proceed-with-an-uninstall/1189524#1189524(点击链接了解详情)。

缓存 MSI 的文件夹是:%SystemRoot%\Installer(通常是 C:\Windows\Installer)。每个 MSI 都分配有一个随机的十六进制名称。所有 MSI 文件都将进入此缓存文件夹 - 除非在安装或产品注册过程中出现问题。此文件夹中缺少 MSI 文件是一个严重的问题 - 该产品通常无法卸载,也无法升级。我们开始看到某些安全软件从该文件夹隔离 MSI 文件的问题 - 处理起来可能是一场噩梦 - 但这不是这个答案的重点。

除了这个内置机制之外,第三方供应商可能会将原始安装 MSI 缓存在其他位置以及这个内置的缓存文件夹。这是为了支持修复、修补和修改操作,而不需要任何“源媒体”请求。非常适合家庭和小型办公室用户,但企业用户可能不会欣赏它,因为他们在可从所有工作站访问的网络共享上提供了所有安装源(他们不喜欢此类本地副本)。为了实现这一点,他们通常使用MSI 的内置管理安装功能 https://stackoverflow.com/questions/5564619/what-is-the-purpose-of-administrative-installation-initiated-using-msiexec-a/5751980#5751980- 本质上是创建网络位置共享的标准化方法,以通过提取的文件触发安装(有一个这里是管理设施的另一个描述 https://stackoverflow.com/questions/1547809/extract-msi-from-exe/24987512#24987512- 也许比第一个更注重实用)。

UPDATE: 说实话,我觉得源文件的可选缓存应该从一开始就内置到 Windows Installer 中并成为默认命令行选项(对于家庭和小型办公室用户),然后一个简单的标志就可以轻松地阻止所有企业用户进行此类缓存(例如 NOSOURCECACHING = 1)。还:现在 MSI 文件已全尺寸缓存在 %SystemRoot%\Installer 中 https://stackoverflow.com/questions/208530/why-does-msi-require-the-original-msi-file-to-proceed-with-an-uninstall/1189524#1189524- 看来你仍然无法从那里自动神奇地获取源文件? (最近没有测试)。这是怎么回事?文件就在那里 - 除非安装是通过管理映像进行的(在这种情况下,源可能安全地位于网络共享上,并且在需要时可以访问,从而可以避免本地 PC 混乱)。哦,好吧,将来我们无疑将按需直接从在线存储库中提取文件,这样一个问题就解决了,并且一系列新问题正在酝酿之中?恶意软件、欺骗和注入?远程文件在没有警告的情况下被删除(以摆脱不应再使用的易受攻击的版本 - 让用户陷入困境)?证书和签名有问题吗?防火墙和代理问题?自动魔法更新中不幸的错误会立即影响到每个人吗?只是咆哮:-)。我确信这将在很大程度上得到改善。无论如何,下面的部分将介绍当前的第三方缓存方法(非 MSI 标准)。

2.WiX缓存

WiX 捆绑功能(刻录)可以在系统上缓存 MSI 文件。说实话,我不是 100% 确定他们是如何做到这一点的,我希望Arnson or 门兴 can 如果我错了请在这里纠正我。然而,我相信他们使用:%ProgramData%\Package Cache(通常是 C:\ProgramData\Package Cache)用于缓存。我的系统上有很多不同的 Microsoft 组件,我不确定它们是否都与 WiX 一起打包。

3.安装shield缓存

Installshield可以将原始MSI文件缓存在%SystemRoot%\Downloaded Installations对于某些类型的构建配置。换句话说:并非所有 Installshield 设置都会以这种方式缓存自身 - 这是一个 Installshield 项目构建设置,可以根据设置开发人员的需要打开或关闭。

UPDATE:似乎较新版本的 Installshield 现在可以默认缓存设置%LocalAppData%\Downloaded Installations(通常是 C:\Users\YOURUSERNAME\AppData\Local\Downloaded Installations)而不是%SystemRoot%\Downloaded Installations。我不确定哪个版本切换到了这个位置。或许迈克尔·厄曼 https://stackoverflow.com/users/89999/michael-urmanInstallshield可以帮助我们吗?

4. 高级安装程序缓存

添加者博格丹·米特拉什 https://stackoverflow.com/users/882875/bogdan-mitrache高级安装程序(非常感谢 - 现在它是准确的):从高级安装程序构建的 EXE 获取/复制 MSI 的最简单方法是使用/extract 命令行选项 https://www.advancedinstaller.com/user-guide/exe-setup-file.html.

在安装时,对于 EXE 构建(MSI 捆绑在 EXE 内) 高级安装程序默认在此位置提取内容:

[AppDataFolder][|Manufacturer]\[|ProductName] [|ProductVersion]\install.

如您所见,它取决于供应商,因此每个包的路径都不同。

此外,该路径可以在安装项目中自定义,因此用户可以更改它(大多数时候他们不).

安装完成后还可以选择删除提取的资源,这也是用户可配置的并且默认情况下处于启用状态。

如果您使用高级安装程序构建标准 MSI,则缓存由 Windows Installer 完成,如上所述。

5.Visual Studio 缓存

Visual Studio appears to cache packages under: %AllUsersProfile%\Microsoft\VisualStudio\Packages (normally C:\ProgramData\Microsoft\VisualStudio\Packages). I don't really have a clue how they do things apart from this folder being used. There are also packages here: %ProgramData%\Microsoft\VisualStudio\Packages.

UPDATE: the folder %ProgramData%\Microsoft\VisualStudio\Packages appears to be the same location as above (%AllUsersProfile%\Microsoft\VisualStudio\Packages) only with a symbolic link (the folders point to the same files and folders on disk). It is also possible to disable this caching as described by Heath Stewart here: Moving or disabling the package cache for Visual Studio 2017 https://blogs.msdn.microsoft.com/heaths/2017/04/17/moving-or-disabling-the-package-cache-for-visual-studio-2017/.

这是非 MSI 并且我不熟悉:%ProgramFiles(x86)%\Microsoft SDKs\NuGetPackagesFallback

6. 其他缓存文件夹?

Apple:我对此了解不多,但似乎 Apple 可能会使用此文件夹来缓存一些 MSI 安装程序:%LocalAppData% \Apple\Apple Software Update\(通常为 C:\Users\Acer\AppData\Local\Apple\Apple Software Update)。

Sun:Sun 似乎使用此基本文件夹来缓存 Java 安装 MSI 文件:%UserProfile%\AppData\LocalLow\Oracle\Java(通常为 C:\Users\Acer\AppData\LocalLow\Oracle\Java)。

毫无疑问,还有许多其他缓存文件夹正在使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

msiexec MsiSetExternalUI 的外部处理程序 的相关文章

  • 当从后台工作程序发生事件时,XlCall.Excel(XlCall.xlcCalculateNow) 抛出 XlCallException

    我有一个 ExcelFunction 来排队一些计算 ExcelFunction public static void QueueCalcs takes ranges var calcRequests builds list of calc
  • 通过另一个列表更新列表(linq)

    我有类 Data 的对象列表 如下所示 class Data int code string name DateTime date update 我还有另一个课程列表 例如 class RefCodes int old code int n
  • 当其源是 https uri 时如何使 wpf MediaElement 播放

    在 wpf 独立应用程序 exe 中 我在主窗口中包含了 MediaElement
  • EventHandler 应该始终用于事件吗?

    我一直在愉快地使用自定义委托类型和通用编写事件Action委托类型 没有真正考虑我在做什么 我有一些很好的扩展助手Action and EventHandler这使我倾向于使用那些预定义的委托类型而不是我自己的委托类型 但除此之外 除了惯例
  • 从另一个 FORM 中取回隐藏的 FORM

    我有两种形式Form1 and Form2 我正在打开Form2 from Form1 on button Click Form2 obj2 new Form2 this Visible false obj2 Show 然后我想回来Form
  • C# 和月历,选择多个日期

    我正在制作一个程序 可以帮助人们用 C 为某个部门 预订 订单 他们需要能够选择不同月份的多个日期 我更愿意拥有它 这样他们就可以单击一个日期 然后按住 Shift 键单击另一个日期以选择这两个日期之间的所有日期 并控制单击以进行单选 取消
  • 如何使用 C# 以编程方式编辑 Power BI Desktop 文档参数或数据源?

    我有一个在 Power BI Desktop 中内置的报告模板 并保存为 pbix 或 pbit 文件 该模板使用DirectQuery SQL数据库作为数据源 而服务器地址和数据库名称被提取到参数中 还有一个参数包含一个ReportId
  • MSMQ接收和删除

    是否有任何选项可以在读取消息后将其从 MSMQ 中删除 比如 接收 删除可以作为原子操作运行吗 听起来您想查看下一条消息 然后在处理完成后接收它 Message message Queue Peek Queue ReceiveById me
  • 如何查明 .exe 是否正在 C++ 中运行?

    给定进程名称 例如 程序 exe C 标准库没有这样的支持 您需要一个操作系统 API 来执行此操作 如果这是 Windows 那么您将使用 CreateToolhelp32Snapshot 然后使用 Process32First 和 Pr
  • C# Winforms Designer 无法打开,因为它无法在同一程序集中找到类型

    我收到以下错误 找不到类型 My Special UserControl 请确保引用包含此类型的程序集 如果此类型是您的开发项目的一部分 请确保已使用当前平台或任何 CPU 的设置成功构建该项目 但没有任何意义的是My Special Us
  • 关闭整数的最右边设置位

    我只需要关闭最右边的设置位即可 我的方法是找到最右边位的位置 然后离开该位 我编写这段代码是为了这样做 int POS int n int p 0 while n if n 2 0 p else break n n 2 return p i
  • 判断串口是普通COM还是SPP

    我正在寻找一种方法来确定 COM 是标准 COM 还是 SPP COM 也称为 COM 设备的电缆替换蓝牙适配器 我有一个可以在 USB COM gt USB 和蓝牙下工作的设备 并且蓝牙接口可以与 SPP 一起工作 我目前正在使用Syst
  • 为什么 std::function 不是有效的模板参数,而函数指针却是?

    我已经定义了名为的类模板CallBackAtInit其唯一目的是在初始化时调用函数 构造函数 该函数在模板参数中指定 问题是模板不接受std function作为参数 但它们接受函数指针 为什么 这是我的代码 include
  • MSChart 控件中的自定义 X/Y 网格线

    我有一个带有简单 2D 折线图的 C Windows 窗体 我想向其中添加自定义 X 或 Y 轴标记 并绘制自定义网格线 例如 以突出显示的颜色 虚线 我查看了 customLabels 属性 但这似乎覆盖了我仍然想显示的默认网格 这是为了
  • 在 Qt 中播放通知(频率 x)声音 - 最简单的方法?

    Qt 5 1 或更高版本 我需要播放频率为 x 的通知声音 n 毫秒 如果我能像这样组合音调那就太好了 1000Hz 持续 2 秒 然后 3000Hz 持续 1 秒 最简单的方法是使用文件 WAV MP3 例如如此处所述 如何用Qt播放声音
  • 如何测试某些代码在 C++ 中无法编译? [复制]

    这个问题在这里已经有答案了 可能的重复 单元测试编译时错误 https stackoverflow com questions 605915 unit test compile time error 我想知道是否可以编写一种单元测试来验证给
  • 用数组或向量实现多维数组

    我想使用单个数组或向量实现多维数组 可以像通常的多维数组一样访问它 例如 a 1 2 3 我陷入困境的是如何实施 操作员 如果数组的维数为 1 则 a 1 应该返回位于索引 1 处的元素 但是如果维数大于一怎么办 对于嵌套向量 例如 3 维
  • 当 Verb="runas" 时设置 ProcessStartInfo.EnvironmentVariables

    我正在开发一个 C 应用程序 我需要创建变量并将其传递给新进程 我正在使用ProcessStartInfo EnvironmentVariables 新进程必须提升运行 因此我使用 Verb runas var startInfo new
  • 初始化列表在 VC10 中不起作用

    我在 VC 2010 中编写了这个程序 class class1 public class1 initializer list
  • 如何在c中断言两个类型相等?

    在 C 中如何断言两种类型相等 在 C 中 我会使用 std is same 但搜索 StackOverflow 和其他地方似乎只能给出 C 和 C 的结果 在C中没有办法做到这一点吗 请注意 这不是询问变量是否具有某种类型 而是询问两个类

随机推荐

  • Fragment 中的按钮 setOnClickListener onCreateView() 或 onActivityCreated()

    通过这个答案 https stackoverflow com a 32656807 3838663我不明白该把我的东西放在哪里onClickListener 里面onCreateView 或里面onActivityCreated 下面的代码
  • 位桶中没有问题跟踪器按钮?

    我正在尝试在 bitbucket 私有存储库上设置问题跟踪 但没有用于管理 添加问题的按钮 在this https confluence atlassian com bitbucket use the issue tracker 22144
  • ASP.NET MVC 4 - 用于嵌套集合的 EditorTemplate

    我有以下模型类 为了解决这个问题而简化了类 public class Lesson public Guid Id get set public string Name get set public List
  • 触发复选框的更改事件

    我有 7 个复选框 A B C D E F G 当我单击其中之一时 该值将附加到文本区域 如果我取消选中一项 该值将从文本区域中删除 jquery代码如下 var checkboxes input type checkbox checkbo
  • facet_grid 中每个图基于密度的独立 alpha

    我正在构建一个facet grid using stat hexbin但是我希望每个方面图的 alpha 值都是独立的 我目前正在使用以下代码 ggplot data aes x y fill z stat binhex bins 20 a
  • 在 Bash 中连接变量[重复]

    这个问题在这里已经有答案了 我正在尝试将一个变量添加到变量的中间 因此例如在 PHP 中我会这样做 mystring arg1 12 arg2 endoffile 所以输出可能是20121201endoffile 如何在 Linux bas
  • E492:不是编辑器命令:NERDTree

    当我跑步时vim 打开文件夹时出现以下错误 Error detected while processing VimEnter Auto commands for E492 Not an editor command NERDTree Pre
  • Firefox 插件的“document_start”?

    我来自 Chrome 扩展 所以我习惯于通过设置来定义何时注入文件run at 例如 到document start用于在 DOM 构建之前进行注入 Firefox 插件有等效的吗 是的 相当于content document global
  • 用户提供的 Terminate() 函数必须是线程安全的吗?

    如中所述http en cppreference com w cpp error terminate http en cppreference com w cpp error terminate调用终止的原因有很多 我可以想象其中一些原因几
  • 在 Ruby 数组中收集重复项的最快/单行方法?

    转换数组的最快 单行方法是什么 1 1 1 1 2 2 3 5 5 5 8 13 21 21 21 到这样的对象数组中 1 gt 4 2 gt 2 3 gt 1 5 gt 3 8 gt 1 13 gt 1 21 gt 3 为了实现您想要的格
  • 如何等待WPF绑定延迟完成

    我的 ViewModel 实现了 INotifyPropertyChanged 和 INotifyDataErrorInfo 接口 当属性更改时 将触发验证 从而启用 禁用 保存 按钮 由于验证步骤非常耗时 因此我使用了 延迟 绑定属性 我
  • GAPI 的 OAuth - 首次登录 Javascript 后避免身份验证和授权

    我创建了一个 chrome 扩展 可以读取电子邮件 执行某些操作并使用 javascript 的 google 客户端 API 创建任务 我使用 chrome 身份进行身份验证和授权 扩展按预期工作 然而 它每隔一段时间就会要求签名 我想要
  • Boost::Log 和日志编号

    我最近尝试通过 Boost log 将一些日志记录添加到一个小型应用程序中 但是 使用日志轮换 由于某种原因 我无法让它在日志目录中拾取正确的计数器 例如 如果我的Logs目录包含文件Log 000 log and Log 001 log我
  • 将 javascript 注入 SwiftUI WebKit

    如何将 SwiftUI WebKit 视图的文本大小设置为 State 变量 我有这段代码 允许我在 SwiftUI 中使用 WebViews import SwiftUI import WebKit struct WebView UIVi
  • 如何在 Angular 2 中实现 Chart.js?

    我正在使用最新版本的 Angular 2 V4 0 0 并且我想在我的项目中使用 Chart js 库中的图表 而不会有太多复杂性 如何在我的 Angular 项目中实现 Chart js 并且不会在最终生产中给我带来问题 您可以按照以下说
  • 如何在Opencart中添加子选项?

    我使用的是最新的3 0 2 0版本的opencart 对于选项 我想添加子选项 我也想像选项一样对子选项进行定价 从 2009 年及更早的时间起 有很多关于 opencart 的依赖选项的讨论 但它从未出现在核心版本中 为什么大家都说实现依
  • 有任何 API 或 Web UI 项目来管理 Docker 私有注册表吗?

    我找不到如何管理私人注册表中的图像 我可以推送或拉取图像 因为我知道 id 但如何获取推送图像的列表 举例来说 一个人想要查看其组织的私人注册表下的可用图像 她该怎么办 除非我弄错了 否则我找不到 API 或 Web UI 来发现注册表内容
  • 更改 Mac/Linux 上进程的用户所有者?

    我有一个以 root 身份运行的程序 该应用程序调用另一个程序 processA 来运行 当 processA 运行时 它由 root 拥有 但我希望它的所有者是当前登录的用户 怎么做 嗯 这有点棘手 取决于它是守护进程 服务 还是运行此命
  • 可以从 Google Chrome 设置面板中的地址栏(小书签)运行 Javascript 吗?

    我想制作一个书签来打开谷歌浏览器的设置面板并通过单击清除我的缓存 一段时间以来 我有一个书签 可以打开 Chrome 的设置面板 并已选择 清除缓存 设置 单击书签 通常在新选项卡中打开它 后 我必须打开该选项卡并提交表单 然而 在开发时
  • msiexec MsiSetExternalUI 的外部处理程序

    早上好 我希望为 msiexec 实现一个外部处理程序 但不能阻止 msiexec 执行任何不同的操作 我希望能够利用 MsiSetExternalUI 拦截所有消息 但仍然对最终用户具有相同的响应和对话框 我的主要目标是拦截安装 msi