我们的许多客户都可以访问InstallShield,WISE或AdminStudio。这些都不是问题。我希望有一些方法可以提供我们的小客户无法访问商业重新包装工具一套免费提供的工具和步骤来自行更换文件。
只需要替换压缩MSI中的单个配置文件,可以假定目标用户已经安装了Orca,知道如何使用它来自定义Property表(嵌入GPO部署的许可证详细信息)并生成一个MST文件。
免责声明:这与another question非常相似,但该主题中的问题和答案都不明确。
答案 0 :(得分:9)
好的,用我自己的答案重新审视这个问题,提供一个很好的小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配合使用。
答案 1 :(得分:2)
我认为您自己创建了msi文件(?)
当您使用Wix生成msi时,客户可以在替换文件后重新生成整个msi(wix是免费的)。否则,应该可以使用未嵌入在msi中的未压缩文件。在wix中,您必须添加media element而不使用cabinet属性。缺点是您必须分发两个文件,而不是一个msi。
答案 2 :(得分:2)
恕我直言,这种情况表明正在安装的应用程序中缺少一项功能,并且比使用MSI进行攻击更容易修复应用程序。
首先我要说的是,为用户“解决”这个问题的一种简单方法是告诉他们运行MSI的管理员安装。这实际上将从内部CAB中提取所有文件,并将所有文件放在指定的文件夹中:
msiexec.exe / a myinstaller.msi TARGETDIR = C:\ AdminImage
然后,您的用户可以直接进入解压缩的文件夹结构并更新相关文件,然后将目录映射到其他PC并安装MSI。这可能会产生副作用,因为文件在MSI中有一个哈希值(以避免欺骗),但在大多数情况下它可以正常工作。
新版本的部署工具(如Installshield和Wix)具有内置支持,可在安装期间运行XPath查询,从而动态编写部分。
在PC上设置应用程序涉及几个步骤。首先是内容部署到机器 - 这应该使用MSI完成,毫无疑问。但是,在大多数高级应用程序中,需要几个类似于“配置文件更新”的“安装后配置任务”。
在应用程序启动之前推迟这些配置任务几乎总是更好,而不是在MSI中实现功能。这有很多原因,但最重要的是只保证应用程序EXE在正确的用户上下文中运行。 MSI文件可以使用系统权限,不同的用户帐户或其他机制运行。
我们通常建议使用MSI 将所有必需内容添加到PC 。然后标记注册表以向应用程序指示它是第一次启动(对于更新,您可以递增计数器或将新版本号写入HKLM)。然后,应用程序可以在其启动例程中执行最终配置步骤。它可以从%ProgramFiles%中的某个位置复制默认的config.xml文件,并将其复制到用户配置文件中。然后它可以从MSI编写的HKLM中读取所需的值,然后使用这些值更新config.xml文件。
通常:避免由MSI或任何其他设置机制执行的配置步骤。专注于将所需的文件和注册表项写入计算机,然后让应用程序本身设置适当的运行时环境。这将允许更好的部署控制。如果你愿意,这是更好的“封装”。 MSI通过注册表向应用程序发送“消息”,应用程序根据消息知道“如何正确设置自己”。
答案 3 :(得分:1)
您需要在Media表中添加一个条目,添加另一个没有cabinet文件的媒体,以及一个比CAB文件的最后一个序列多一个的LastSequence。然后,您需要在File表中将文件的序列替换为新文件,并更新可能已更改的所有其他文件属性。
答案 4 :(得分:1)
检查以下帖子: How to replace a file in a msi installer?
提到的地方:
此命令提取MSI文件: msi2xml -c OutputDir TestMSI.MSI
打开OutputDir并修改文件。
要重建MSI运行: xml2msi.exe -m TestMSI.xml
您需要-m忽略修改MSI文件时失败的'MD5校验和测试'。