我正在寻找使用VBScript从MSI外部安装或不安装(以较快者为准)解析MSI中文件的路径。
我发现使用C#的类似查询而Christopher提供了一个解决方案,如下所示:How can I resolve MSI paths in C#?
我现在正经历着同样的痛苦,但无论如何都要在VBScript中使用WindowsInstaller对象来实现这一点,而不是通过MSI来回的SQL表进行无休止的查询来实现相同的目标。虽然任何方向都会很受欢迎,因为我已经尝试过尽我所能,只取得了非常有限的成功。
答案 0 :(得分:5)
是的,没有安装msi和使用vbscript的解决方案。 Windows Installer SDK中有一个名为“WiFilVer.vbs”
的非常好的示例使用该示例我将一个快速示例脚本拼凑在一起,完全符合您的需要。
set installer = CreateObject("WindowsInstaller.Installer")
const READONLY = 0
set db = installer.OpenDataBase("<FULL PATH TO YOUR MSI>", READONLY)
set session = installer.OpenPackage(db, READONLY)
session.DoAction("CostInitialize")
session.DoAction("CostFinalize")
set view = db.OpenView("SELECT File, Directory_, FileName, Component_, Component FROM File,Component WHERE Component=Component_ ORDER BY Directory_")
view.Execute
set record = view.Fetch
do until record is nothing
file = record.StringData(1)
directoryName = record.StringData(2)
fileName = record.StringData(3)
if instr(fileName, "|") then fileName = split(fileName, "|")(1)
wsh.echo(session.TargetPath(directoryName) & fileName)
set record = view.Fetch
loop
只需添加MSI文件的路径即可。
告诉我你是否需要更详细的答案。今晚我将有更多时间详细回答这个问题。
编辑承诺的背景(以及为什么我需要调用ConstFinalize)
naveen实际上MSDN是唯一可以给出明确答案的资源,但你需要知道在哪里以及如何看,因为Windows安装程序是恕我直言,这是一个非常复杂的话题。 我真的推荐msdn installer function reference,database reference和windows安装程序SDK中的示例的混合(抱歉找不到下载链接,我认为它隐藏在3GB windows SDK中的某处)
首先,您需要了解MSI的一般知识:
MSI实际上是一个关系数据库。 一切都存储在彼此相关的表中。 (实际上并非一切,但我会尽量保持简单;))
此数据库由Windows Installer解释, 这会创建一个“会话”
也可以动态解析某些部分,具体取决于您安装msi的系统, 像'特殊'文件夹类似于环境变量。 例如。 msi有一个“ProgramFilesFolder”,其中windows通常有%ProgramFiles%。
所有动态内容仅存在于安装程序会话中,而不存在于数据库本身中。
在您的情况下,您需要查看3个表格,处理关系并解决它们。
'File'表包含所有文件,'Component'表告诉您哪个文件进入哪个目录,'Directory'表包含有关文件系统结构的所有信息。
使用SQL查询我可以链接Component和File表来查找目录名(或数据库术语中的主键)。
但目录表本身具有关系,其结构类似于树。 看一下这个示例目录表(取自instEd MSI)
列是Directory,Directory_Parent和DefaultDir
InstEdAllUseAppDat InstEdAppData InstEd
INSTALLDIR InstEdPF InstEd
CUBDIR INSTALLDIR hkyb3vcm|Validation
InstEdAppData CommonAppDataFolder instedit.com
CommonAppDataFolder TARGETDIR .
TARGETDIR SourceDir
InstEdPF ProgramFilesFolder instedit.com
ProgramFilesFolder TARGETDIR .
ProgramMenuFolder TARGETDIR .
SendToFolder TARGETDIR .
WindowsFolder_x86_VC.1DEE2A86_2F57_3629_8107_A71DBB4DBED2 TARGETDIR Win
SystemFolder_x86_VC.1DEE2A86_2F57_3629_8107_A71DBB4DBED2 WindowsFolder_x86_VC.1DEE2A86_2F57_3629_8107_A71DBB4DBED2 System
directory_parent将其链接到目录。 DefaultDir包含实际名称。 您现在可以自己解析树并替换所有特殊文件夹(在vbscript中会非常繁琐)......
...或让Windows安装程序处理(就像安装msi时一样)。 现在我必须引入一个新的东西:动作(和序列): 当运行(安装,删除,修复)msi时,执行定义的动作列表。 有些动作只是收集信息,有些则会改变实际的数据库。
有msi可以执行的各种操作的动作列表(称为序列), 就像一个安装序列(称为InstallExecuteSequence),一个用于从用户收集信息(MSI的UI:InstallUISequence)或一个用于管理点安装(AdminExecuteSequence)。
在我们的例子中,我们不想运行整个序列(可能会改变系统或只需要长时间), 幸运的是,Windows安装程序允许我们运行单个操作而无需运行整个序列。 阅读reference of the directory table on MSDN(备注部分),您可以看到所需的操作:
Directory resolution is performed during the CostFinalize action
所以将所有这些放在一起更容易阅读 *打开msi文件 *'解析'它(提供会话) *查询组件和文件表 *运行CostFinalize操作来解析目录表(不运行整个MSI) *使用targetPath函数获取已解析的路径
顺便说一句,我通过浏览MSDN上的安装程序参考找到了targetPath函数 我也注意到不需要CostInitialize。如果你想获取文件的sourcePath,它只是必需的。
我希望这会让一切变得清晰,很难解释,因为我花了半年的时间来理解它;)
关于PhilmEs的回答: 是的,对目录表的解析有更多影响,比如自定义操作。 记住这一点,管理安装可能会导致不同的directorys(例如,因为不同的序列可能会持有不同的自定义操作)。 组件有条件,因此可能根本没有安装文件。 我非常确定InstEd也不会考虑自定义操作。
是的,没有100%的解决方案。也许一切都是必要的。
答案 1 :(得分:2)
weberik提供的脚本(源自MS SDK VB代码)非常好,因为它可以在没有自己的算法的情况下轻松分析目录表(这是一个中等规模的工作,可以在循环中或使用递归算法)。 但它并没有为所有文件提供100%完美的视图,请参见下文。 该脚本的方法是半动态的(可以通过其他操作扩展),但实际上它只提供静态目录结构,类似于默认的管理安装或高级MSI查看器。
通常这就足够了,我们想要什么。 但要注意,这不是100%的解决方案(事先知道每个文件的路径)。这意味着,在某些情况下,这不会给你总是正确的路径:
实际上,100%的解决方案非常难以实现,没有真正安装。它接近重新编程几乎整个Windows安装程序引擎。因此,简化通常是充分的并且被接受。
但您可以扩展该方法以涵盖自定义操作,例如为每个需要的其他操作添加一行“session.DoAction(..)”。或者包含命令行参数。
有时它可能很棘手。 MSI的结构越容易,你就越有可能在没有更多努力的情况下取得成功。
编写自己的程序的替代方法: 问题是,您真正想要找到的是什么,以及是否真的有必要对其进行编程: 如果您不想编写一个自动的每日MSI分析仪,可能以下内容就足够了:
第一个提示:使用“msiexec / a mysetup.msi TARGETDIR =”c:\ mytestpath“安装MSI。(与weberik上面的脚本类似的限制) 如果MSI没有使用自定义操作来更改路径,包括忘记添加到管理序列(“忘记”应该被视为99%或现有设置的正常情况:-),您将得到文件结构,如果您安装“真的“对于Windows预定义文件夹有一些特殊的命名,你可以轻松找到它们。
如果管理安装缺少某些文件夹,则通常更好的方法是修复自定义操作(添加到管理序列)并将此方案用作主要测试用例。 优点是,只有你限制了admin安装使用的动态。顺便说一句,您可以使用与实际安装相同的命令行参数或路径设置自定义操作。
第二个提示:Google for InstEd工具,转到文件或组件表,您将在调用CostInitialize / CostFinalize后以与提到的VB脚本相同的静态方式查看生成的MSI路径。对于人类观点,这样的编辑器视图可能更好。
对于自动测试和改进或准确性,您当然需要一个自己的程序。 对于那些提到片段的人来说,这是一个很好的起点。 : - )
你们其他人应该在没有编程的情况下使用两种给定方法之一生活得更轻松。