替换 MSI 内小文件的最简单解决方案?

发布于 2024-07-09 07:04:50 字数 414 浏览 11 评论 0原文

我们的许多客户都可以访问 InstallShield、WISE 或 AdminStudio。 这些都不是问题。 我希望有某种方法可以为我们的小客户无需使用商业重新打包工具提供一组免费的工具和步骤来自行进行文件替换。

只需要替换压缩的 MSI 中的单个配置文件,可以假设目标用户已经安装了 Orca,知道如何使用它来自定义属性表(嵌入 GPO 部署的许可证详细信息)并生成了 MST 文件。



免责声明这与 另一个问题,但该线程中的问题和答案都不清楚。

Many of our customers have access to InstallShield, WISE or AdminStudio. These aren't a problem. I'm hoping there is some way I can provide our smaller customers without access to commercial repackaging tools a freely available set of tools and steps to do the file replacement themselves.

Only need to replace a single configuration file inside a compressed MSI, the target user can be assumed to already have Orca installed, know how to use this to customize the Property table (to embed license details for GPO deployment) and have generated an MST file.

Disclaimer: this is very similar to another question but both questions and answers in that thread are not clear.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

嗼ふ静 2024-07-16 07:04:50

好吧,用我自己的答案重新审视这个问题,提供了一个不错的小 VB 脚本,可以完成所有繁重的工作。 正如原始问题中所提到的,目的是为系统管理员用户提供一个简单的解决方案来自行进行更新/更改。

下面是我当前向客户提供的代码的简化版本

Option Explicit

Const MY_CONFIG = "MyConfigApp.xml"
Const CAB_FILE = "config.cab"
Const MSI = "MyApp.msi"

Dim filesys : Set filesys=CreateObject("Scripting.FileSystemObject")

If filesys.FileExists("temp.tmp") Then filesys.DeleteFile("temp.tmp")
filesys.CopyFile MSI, "temp.tmp"

Dim installer, database, database2, view
Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase ("temp.tmp", 1)
Set database2 = installer.OpenDatabase (MSI, 1)

If Not filesys.FileExists(MY_CONFIG) Then WScript.Quit 2 ' No config file, abort!

Dim objFile, size, result, seq, objCab

' MakeCab object has been depreciated so we fallback to makecab.exe for with Windows 7
On Error Resume Next ' Disable error handling, for a moment
Set objCab = CreateObject("MakeCab.MakeCab.1") 
On Error Goto 0  ' Turn error handling back on

If IsObject(objCab) Then ' Object creation successful - use XP method   
    objCab.CreateCab CAB_FILE, False, False, False
    objCab.AddFile MY_CONFIG, filesys.GetFileName(MY_CONFIG)
    objCab.CloseCab
    Set objCab = Nothing
Else ' object creation failed - try Windows 7 method
    Dim WshShell, oExec
    Set WshShell = CreateObject("WScript.Shell")
    Set oExec = WshShell.Exec("makecab " & filesys.GetFileName(MY_CONFIG) & " " & CAB_FILE)
End If

Set objFile = filesys.GetFile(MY_CONFIG)
size = objFile.Size

Set view = database.OpenView ("SELECT LastSequence FROM Media WHERE DiskId = 1")
view.Execute
Set result = view.Fetch
seq = result.StringData(1) + 1 ' Sequence for new configuration file

Set view = database.OpenView ("INSERT INTO Media (DiskId, LastSequence, Cabinet) VALUES ('2', '" & seq & "', '" & CAB_FILE & "')")
view.Execute

Set view = database.OpenView ("UPDATE File SET FileSize = " & size & ", Sequence = " & seq & ", FileName = 'MYC~2.CNF|MyConfigApp.xml' WHERE File = '" & MY_CONFIG & "'")
view.Execute

database.GenerateTransform database2, "CustomConfig.mst"
database.CreateTransformSummaryInfo database2, "CustomConfig.mst", 0, 0
filesys.DeleteFile("temp.tmp")

Set view = nothing
Set installer = nothing
Set database = nothing
Set database2 = nothing
Set filesys = Nothing
WScript.Quit 0

更新:MakeCab.MakeCab.1 对象已被折旧,代码已更新,现在可在 Windows 7 上使用。

Okay, revisiting this question with my own answer providing nice little VB script that will do all heavy lifting. As mentioned in the original question, the aim was provide a simple solution for sysadmin users to make the updates/changes themselves.

Below is a simplified version of the code I'm currently providing to customers

Option Explicit

Const MY_CONFIG = "MyConfigApp.xml"
Const CAB_FILE = "config.cab"
Const MSI = "MyApp.msi"

Dim filesys : Set filesys=CreateObject("Scripting.FileSystemObject")

If filesys.FileExists("temp.tmp") Then filesys.DeleteFile("temp.tmp")
filesys.CopyFile MSI, "temp.tmp"

Dim installer, database, database2, view
Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase ("temp.tmp", 1)
Set database2 = installer.OpenDatabase (MSI, 1)

If Not filesys.FileExists(MY_CONFIG) Then WScript.Quit 2 ' No config file, abort!

Dim objFile, size, result, seq, objCab

' MakeCab object has been depreciated so we fallback to makecab.exe for with Windows 7
On Error Resume Next ' Disable error handling, for a moment
Set objCab = CreateObject("MakeCab.MakeCab.1") 
On Error Goto 0  ' Turn error handling back on

If IsObject(objCab) Then ' Object creation successful - use XP method   
    objCab.CreateCab CAB_FILE, False, False, False
    objCab.AddFile MY_CONFIG, filesys.GetFileName(MY_CONFIG)
    objCab.CloseCab
    Set objCab = Nothing
Else ' object creation failed - try Windows 7 method
    Dim WshShell, oExec
    Set WshShell = CreateObject("WScript.Shell")
    Set oExec = WshShell.Exec("makecab " & filesys.GetFileName(MY_CONFIG) & " " & CAB_FILE)
End If

Set objFile = filesys.GetFile(MY_CONFIG)
size = objFile.Size

Set view = database.OpenView ("SELECT LastSequence FROM Media WHERE DiskId = 1")
view.Execute
Set result = view.Fetch
seq = result.StringData(1) + 1 ' Sequence for new configuration file

Set view = database.OpenView ("INSERT INTO Media (DiskId, LastSequence, Cabinet) VALUES ('2', '" & seq & "', '" & CAB_FILE & "')")
view.Execute

Set view = database.OpenView ("UPDATE File SET FileSize = " & size & ", Sequence = " & seq & ", FileName = 'MYC~2.CNF|MyConfigApp.xml' WHERE File = '" & MY_CONFIG & "'")
view.Execute

database.GenerateTransform database2, "CustomConfig.mst"
database.CreateTransformSummaryInfo database2, "CustomConfig.mst", 0, 0
filesys.DeleteFile("temp.tmp")

Set view = nothing
Set installer = nothing
Set database = nothing
Set database2 = nothing
Set filesys = Nothing
WScript.Quit 0

Update: The MakeCab.MakeCab.1 object has been depreciated, code updated to now work with Windows 7.

放手` 2024-07-16 07:04:50

恕我直言,这种情况表明正在安装的应用程序中缺少功能,并且在应用程序中修复比使用 MSI 更容易。


管理映像

首先我要说的是,为用户“解决”此问题的一个简单方法是告诉他们运行 MSI 的管理安装。 这实际上会从内部 CAB 中提取所有文件,并将所有文件放入指定文件夹中:

msiexec.exe /a myinstaller.msi TARGETDIR=C:\AdminImage

您的用户然后可以直接进入提取的文件夹结构并更新有问题的文件,然后将该目录映射到其他 PC 并安装 MSI。 这可能会产生与 MSI 中具有哈希值的文件相关的副作用(以避免欺骗),但在大多数情况下它工作正常。


运行 XML XPath 查询

新版本的部署工具(例如 Installshield 和 Wix)内置支持在安装期间运行 XPath 查询,因此可以动态写入部分。


应用程序更新

在 PC 上设置应用程序涉及多个步骤。 首先是将内容部署到机器上 - 这应该使用 MSI 来完成,毫无疑问。 然而,在大多数高级应用程序中,需要几个类似于此“配置文件更新”的“安装后配置任务”。

将这些配置任务推迟到应用程序启动几乎总是比在 MSI 中实现功能更好。 造成这种情况的原因有很多,但最重要的是只有应用程序 EXE 才能保证在正确的用户上下文中运行。 MSI 文件可以使用系统权限、不同的用户帐户或通过某种其他机制运行。

我们通常建议使用 MSI 将所有必需的内容传输到 PC 上。 然后标记注册表以向应用程序表明这是第一次启动(对于更新,您可以增加计数器或将新版本号写入 HKLM)。 然后应用程序可以在其启动例程中执行最终的配置步骤。 它可以从 %ProgramFiles% 中的某个位置复制默认的 config.xml 文件,并将其复制到用户配置文件中。 然后它可以从 MSI 写入的 HKLM 中读取所需的值,然后使用这些值更新 config.xml 文件。

一般来说:避免由 MSI 或任何其他设置机制执行的配置步骤。 集中精力将所需的文件和注册表项写入机器,然后让应用程序本身设置适当的运行环境。 这将允许更好的部署控制。 如果你愿意的话,最好是“封装”。 MSI 通过注册表向应用程序发送一条“消息”,应用程序根据该消息知道“如何正确设置自身”。

IMHO this kind of scenario indicates a missing feature in the application being installed, and is easier to fix in the application than hacking around with the MSI.


Admin Image

Let me first say that a simple way to "solve" this for your users, is to tell them to run an Admin Installation of your MSI. This will essentially extract all the files from the internal CABs and put all files in the specified folder:

msiexec.exe /a myinstaller.msi TARGETDIR=C:\AdminImage

Your users can then go directly into the extracted folder structure and update the file in question and then map the directory to other PC's and install the MSI. There could be side effects to this relating to the file having a hash value in the MSI (to avoid spoofing), but in most cases it works fine.


Run XML XPath Query

New versions of deployment tools such as Installshield and Wix feature built-in support for running XPath queries during the installation and hence write sections dynamically.


Application Update

Setting up an application on a PC involves several steps. First there is the deployment of content to the machine - this should be done using an MSI, no question about it. However, in most advanced applications several "post installation configuration tasks" similar to this "config file update" are required.

It is almost always better to defer these configuration tasks until the application launch, rather than to implement features in the MSI. There are many reasons for this, but the most important being that only the application EXE will be guaranteed to run in the correct user context. MSI files can be run with system rights, a different user account or via some other mechanism.

What we generally recommend is to use the MSI to get all required content onto the PC. Then tag the registry to indicate to the application that it's the first launch (for updates, you can increment a counter or write the new version number to HKLM). Then the application can perform the final configuration steps in its startup routine. It can copy a default config.xml file from somewhere in %ProgramFiles% and copy it to the user profile. Then it can read required values from HKLM written by the MSI, and then update the config.xml file with these values.

In general: avoid configuration steps performed by MSI or any other setup mechanism. Concentrate on writing the required files and registry items to the machine, and then let the application itself set up a proper runtime environment. This will allow much better deployment control. It is better "Encapsulation" if you like. The MSI sends a "message" to the application via the registry, and the application knows "how to set itself up correctly" based on the messages.

抚你发端 2024-07-16 07:04:50

我假设您自己创建 msi 文件(?)

当您使用 Wix 生成您的 msi 时,客户替换文件后可以简单地重新生成整个 msi(wix 是免费的)。 否则,应该可以使用未嵌入 msi 中的未压缩文件。 在wix中,您必须添加一个不带cabinet属性的媒体元素。 缺点是您必须分发两个文件,而不是单个 msi。

I asume that you create the msi file yourself (?)

When you use Wix to generate your msi, the customer can simply regenerate the whole msi after replacing the file (wix is free). Otherwise it should be possible to use an uncompressed file which is not embedded in the msi. In wix you have to add a media element without a cabinet attribute. The disadvantage is that you have to distribute two files, instead of a single msi.

倾其所爱 2024-07-16 07:04:50

您需要向 Media 表添加一个条目,添加另一种媒体没有 Cabinet 文件,并且 LastSequence 比 CAB 文件的最后一个序列多一个。 然后,您需要替换 File 表使用新文件更改文件的顺序,并更新可能已更改的所有其他文件属性。

You need to add an entry to the Media table, adding another medium with no cabinet file, and a LastSequence one more than the CAB file's last sequence. You then need to replace in the File table the file's sequence with the new file, and update all the other file attributes that may have changed.

剩一世无双 2024-07-16 07:04:50

检查以下帖子:
如何替换 msi 安装程序中的文件?

其中提到:

此命令提取 MSI 文件:
msi2xml -c OutputDir TestMSI.MSI

打开 OutputDir 并修改文件。

要重建 MSI,请运行:
xml2msi.exe -m TestMSI.xml

您需要 -m 来忽略修改 MSI 文件时失败的“MD5 校验和测试”。

下载:
https://msi2xml.sourceforge.io/

Check the following post:
How to replace a file in a msi installer?

Where is mentionned:

This command extracts the MSI files:
msi2xml -c OutputDir TestMSI.MSI

Open OutputDir and modify the file.

To rebuild the MSI run:
xml2msi.exe -m TestMSI.xml

You need the -m to ignore the 'MD5 checksum test' that fails when an MSIs file(s) are modified.

Download:
https://msi2xml.sourceforge.io/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文