代码之家  ›  专栏  ›  技术社区  ›  user1403598

msiexec MsiSetExternalUI的外部处理程序

  •  0
  • user1403598  · 技术社区  · 8 年前

    早上好

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

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

    我已尝试使用日志记录使用日志记录注册表项,但可以删除包的源位置,并且在我截获日志文件并获取msi位置之前,包的源将不存在。

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

    为什么一些包被缓存,而其他包则没有?

    因此,我希望使用外部UI,但要确保行为保持不变。

    我目前正在测试一个项目

    MsiInterop。MsiSetExternalUI(新 MsiInstallUIHandler(\u OnExternalUI), MsiInstallLogMode。外部用户界面(ExternalUI,IntPtr)。零);

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

    3 回复  |  直到 8 年前
        1
  •  3
  •   Stein Åsmul    8 年前

    “意图”

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

    您希望找到安装期间缓存的MSI的确切路径 %SystemRoot%\Installer 安装MSI期间?

    我从没试过,但是 萨沙博蒙特 多年前发布了一个VBScript,它似乎试图执行您想要的操作(尽管不是在安装过程中): WiX Custom Action - MSI copy itself . 我从未尝试过这个脚本,也不想推荐它。

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


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


    MsiSetExternalUI

    我看不出你需要如何访问日志 MsiSetExternalUI 要获取MSI文件缓存,请访问以下链接:


    有关MSI缓存的详细信息

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

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

    1、Windows Installer(msiexec.exe)缓存

    有一个内置的Windows Installer功能,可以在安装过程中缓存原始MSI安装数据库的副本。这个缓存的副本以前会剥离内部CAB文件(使其比原始文件小得多),但是 this changed around Windows 7 and the MSI copies are now cached full-size (有关详细信息,请参阅链接)。

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

    除了此内置机制之外,第三方供应商还可以在其他位置缓存原始安装MSI 以及此内置缓存文件夹 . 这是为了支持修复、修补和修改操作,而无需任何“源介质”请求。非常适合家庭和小型办公室用户,但公司用户可能不喜欢它,因为他们在网络共享上有所有安装源,可以从所有工作站访问(他们不喜欢这种本地副本)。为此,他们通常使用 MSI's built-in administrative installation feature -本质上是一种创建网络位置共享的标准化方法,可通过提取的文件触发安装(有 another description of administrative installations here -可能比第一个更注重实际)。

    更新 :老实说,我认为 源文件的可选缓存应该从一开始就内置到Windows Installer中 并且是默认的命令行选项(对于家庭和小型办公室用户),然后一个简单的标志可以很容易地阻止所有公司用户进行此类缓存(例如NOSOURCECACHING=1)。也: now that MSI files are cached full-size in %SystemRoot%\Installer -你似乎仍然不能从那里自动神奇地获取源文件?(最近未测试)。这是怎么回事?文件就在那里,除非安装是从管理映像进行的(在这种情况下,源可能安全地位于网络共享上,并且在需要时可以访问,这样就可以避免本地PC混乱)。哦,好吧,将来我们无疑会按需直接从在线存储库中提取文件,所以一个问题解决了,一堆新的问题正在准备中?恶意软件、欺骗和注射?在没有警告的情况下删除远程文件(以消除不应再使用的易受攻击的版本-使用户陷入困境)?证书和签名问题?防火墙和;代理问题?自动魔法更新,不幸的错误会立即影响所有人?只是咆哮:-)。我相信这将在很大程度上是一种进步。无论如何,在下面的章节中,继续介绍当前的第三方缓存方法(非MSI标准)。

    2、WiX缓存

    WiX捆绑包功能(Burn)可以在系统上缓存MSI文件。我不是百分之百确定他们是怎么做到的,老实说,我希望 阿森 门兴 可以 如果我错了,请纠正我 . 然而,我相信他们使用: %ProgramData%\Package Cache (通常为C:\ProgramData\Package Cache)进行缓存。我的系统中有很多不同的Microsoft组件,我不确定它们是否都是用WiX打包的。

    3、Installshield缓存

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

    更新 :Installshield的较新版本现在似乎可以在以下位置默认缓存设置: %LocalAppData%\Downloaded Installations (通常是C:\Users\YOURUSERNAME\AppData\Local\Downloaded Installation),而不是 %SystemRoot%\下载的安装 . 我不确定哪个版本切换到了这个位置。大概 Michael Urman

    4、高级安装缓存

    添加人 Bogdan Mitrache 高级安装程序(非常感谢-现在它是准确的):从高级安装程序构建的EXE获取/复制MSI的最简单方法是使用 /extract command line option .

    安装时,对于EXE生成( MSI捆绑在EXE中 )默认情况下,高级安装程序会在此位置提取内容:

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

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

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

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

    如果您正在使用Advanced Installer构建标准MSI,则缓存由Windows Installer完成,如上所述。

    5、Visual Studio缓存

    Visual Studio将在以下位置缓存包: %AllUsersProfile%\Microsoft\VisualStudio\Packages (通常为C:\ProgramData\Microsoft\VisualStudio\Packages)。除了正在使用的这个文件夹,我真的不知道他们是怎么做的。这里还有一些软件包: %ProgramData%\Microsoft\VisualStudio\Packages .

    更新 %ProgramData%\Microsoft\VisualStudio\Packages 似乎与上述位置相同( %AllUsersProfile%\Microsoft\VisualStudio\Packages )仅使用符号链接(文件夹指向磁盘上相同的文件和文件夹)。也可以禁用此缓存,如Heath Stewart所述: Moving or disabling the package cache for Visual Studio 2017 .

    这不是MSI,我也不知道: %ProgramFiles(x86)%\Microsoft SDKs\NuGetPackagesFallback

    6、其他缓存文件夹?

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

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

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

        2
  •  0
  •   PhilDW    8 年前

    我不明白为什么拦截UI与安装过程中无法更改的缓存位置有关。然而,现在还不清楚您打算在这里使用“缓存”的确切用途。我假设您引用的是完整的MSI文件,该文件可能已提取到某个安装位置,或者位于安装位置。

    让我们假设安装已经完成,并且您知道(或可以获得)其产品代码。要获取所有官方源位置,只需调用MsiSourceListEnumSources(),这将告诉您Windows在需要时用于查找MSI以进行维护、升级、修复等的实际位置。

    如果源MSI位于您不批准的位置,请使用MsiSourceListClearSource()删除该条目,将MSI复制到您选择的位置,然后使用MsiSourceListAddSource()添加该位置。对于这种类型的管理活动,有很多sourcelist API,例如从不再可用的网络位置安装产品时。

    我认为您不应该移动或更改通常位于\windows\installer中的内部缓存(模糊名称)MSI文件。我们有时称之为缓存位置,但您似乎指的是用于安装产品的完整MSI。

        3
  •  0
  •   Haroldo Gondim smargo    8 年前

    谢谢Bogdan和Stein,我不知道不同类型的安装程序使用不同的缓存文件夹。

    我提出了一个半解决方案,并通过外部UI重定向和连接。我决定只设置某些标志

    ExternalUINoDialog = FatalExit | Error | Warning | User | CommonData | Progress from Interop in the msiexec
    

    这也允许用户输入对话框中的标准行为。我还根据从参数接收到的开关来设置内部UI。

    我注意到一些随机和孤立的情况,例如Microsoft Wonder way as使用:

    MsiExec.exe -Embedding /V
    

    有人知道交换机嵌入了什么吗?我尝试过搜索,但主要的搜索总是会出现病毒问题和msiexec?

    如果有人知道MSDN上的文档?我看过msiexec/?但没有提到嵌入?