如何在 VBScript 中解析 MSI 路径? [英] How can I resolve MSI paths in VBScript?

查看:24
本文介绍了如何在 VBScript 中解析 MSI 路径?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找使用 VBScript 从 MSI 外部安装或不安装(以较快者为准)的情况下解析 MSI 中文件的路径.

I am looking for resolving the paths of files in an MSI with or without installing (whichever is faster) from outside an MSI, using VBScript.

我发现了一个类似的使用 C# 的查询,而 Christpher 提供了一个解决方案,如下所示:如何在 C# 中解析 MSI 路径?

I found a similar query using C# instead and Christpher had provided a solution, below: How can I resolve MSI paths in C#?

我现在正在经历同样的痛苦,但无论如何都可以使用 VBScript 中的 WindowsInstaller 对象来实现这一点,而不是通过 MSI 的 SQL 表来回进行无休止的查询来实现相同的目标.尽管任何方向都会受到欢迎,因为我已经尝试过尝试,但成功率非常有限.

I am going through the very same pain now but is there anyway to achieve this using WindowsInstaller object in VBScript, rather than go with endless queries through SQL Tables of MSI back and forth to achieve the same. Though any direction would be welcoming as I have tried tested whatever I can with very limited success.

推荐答案

是的,有一个无需安装 msi 和使用 vbscript 的解决方案.Windows Installer SDK 中有一个很好的例子,叫做WiFilVer.vbs"

yes there is a solution without installing the msi and using vbscript. there is a very good example in the Windows Installer SDK called "WiFilVer.vbs"

使用那个例子,我已经把一个快速的例子脚本放在一起,它完全符合你的需要.

using that example i've thrown together an quick example script that does exactly what you need.

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 文件即可.

just add the path to your MSI file.

如果您需要更详细的答案,请告诉我.今晚我有更多时间详细回答这个问题.

tell me if you need a more detailed answer. i will have some more time to answer this in detail this evening.

编辑承诺的背景(以及为什么我需要调用 ConstFinalize)

EDIT the promised background (and why i need to call ConstFinalize)

naveen 实际上 MSDN 是唯一可以对此给出明确答案的资源,但是您需要知道在哪里以及如何查看,因为 Windows 安装程序恕我直言是一个非常复杂的主题.我真的推荐混合使用 msdn 安装程序功能参考数据库参考,以及来自 windows installer SDK 的示例(抱歉找不到下载链接,我认为它隐藏在 3GB windows SDK 中)

naveen actually MSDN was the only resource that can give an definitive answer on this, but you need to know where and how to look since windows installer ist IMHO a pretty complex topic. I really recommend a mix of the msdn installer function reference, the database reference, and the examples from the windows installer SDK (sorry couldn't find a download link, i think its somewhere hidden in the like 3GB windows SDK)

首先您需要具备 MSI 的一般知识:

first you need general knowledge of MSIs:

MSI 实际上是一个关系数据库.一切都存储在相互关联的表中.(实际上不是全部,但我会尽量保持简单;))

an MSI is actually a relational database. Everything is stored in tables that relate to each other. (actually not everything, but i will try to keep it simple ;))

该数据库由 Windows 安装程序解释,这将创建一个会话"

This database is interpreted by the Windows Installer, this creates a 'Session'

还有一些部分是动态解析的,具体取决于您安装 msi 的系统,像类似于环境变量的特殊"文件夹.例如.msi 有一个ProgramFilesFolder",windows 通常有 %ProgramFiles%.

also some parts are dynamically resolved, depending on the system you install the msi on, like 'special' folders similar to environment variables. E.g. msi has a "ProgramFilesFolder", where windows generally has %ProgramFiles%.

所有动态内容仅存在于安装程序会话中,而不存在于数据库本身.

All dynamic stuff only exists in the Installer session, not the database itself.

在您的情况下,您需要查看 3 个表,处理关系并解决它们.

In your case there are 3 tables you need to look at, take care of the relations and resolve them.

'File' 表包含所有文件,'Component' 表告诉您哪个文件进入哪个目录,'Directory' 表包含有关文件系统结构的所有信息.

the 'File' table contains all Files, the 'Component' table tells you which file goes into which directory and the 'Directory' table contains all information about the filesystem structure.

使用 SQL 查询,我可以链接组件和文件表以查找目录名称(或数据库行话中的主键).

Using a SQL Query i could link the Component and File table to find the directory name (or primary key in database jargon).

但是目录表本身有关系,它的结构就像一棵树.看看这个示例目录表(取自 instEd MSI)

But the directory table has relations in itself, its structured like a tree. take a look at this example directory table (taken from the instEd MSI)

列分别是 Directory、Directory_Parent 和 DefaultDir

The columns are Directory, Directory_Parent and 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 中会非常乏味)...

The directory_parent links it to a directory. the DefaultDir contains the actual name. You could now resolve the tree by yourself and replace all special folders(which in a vbscript would be very tedious)...

...或者让 Windows 安装程序处理(就像安装 msi 时一样).现在我必须介绍一个新东西:动作(和序列):在运行(安装、删除、修复)msi 时,会执行定义的操作列表.一些操作只是收集信息,一些更改实际的数据库.

...or let the windows installer handle that (just like when installing a msi). now i have to introduce a new thing: Actions (and Sequences): when running (installing, removing, repairing) an msi a defined list of actions is performed. some actions just collect information, some change the actual database.

对于 msi 可以执行的各种操作,有一系列操作(称为序列),例如一种用于安装的序列(称为 InstallExecuteSequence),一种用于从用户收集信息(MSI 的 UI:InstallUISequence)或一种用于管理点安装(AdminExecuteSequence).

there are list of actions (called sequences) for various things a msi can do, like one sequence for installing (called InstallExecuteSequence), one for collecting information from the user (the UI of the MSI: InstallUISequence) or one for adminpoint installations(AdminExecuteSequence).

在我们的例子中,我们不想运行整个序列(这可能会改变系统或花费很长时间),幸运的是,Windows 安装程序允许我们运行单个操作而无需运行整个序列.阅读目录表的参考在 MSDN(备注部分)上,您可以看到您需要哪些操作:

in our case we don't want to run a whole sequence (which could alter the system or just take to long), luckily the windows installer lets us run single actions without running a whole sequence. reading the reference of the directory table on MSDN (the remarks section) you can see which action you need:

Directory resolution is performed during the CostFinalize action

所以把所有这些放在一起,脚本更容易阅读* 打开.msi文件* '解析'它(提供会话)* 查询组件和文件表* 运行 CostFinalize 操作来解析目录表(无需运行整个 MSI)* 使用targetPath函数获取解析路径

so putting all this together the script is easier to read * open the msi file * 'parse' it (providing the session) * query component and file table * run the CostFinalize action to resolve directory table (without running the whole MSI) * get the resolved path with the targetPath function

顺便说一句,我通过浏览 MSDN 上的安装程序参考找到了 targetPath 函数我也只是注意到 CostInitialize 不是必需的.仅当您想获取文件的 sourcePath 时才需要它.

btw i found the targetPath function by browsing the Installer Reference on MSDN also i just noticed that CostInitialize is not required. its only required if you want to get the sourcePath of a file.

我希望这能让一切更清楚,这很难解释,因为我自己花了半年时间才理解它;)

I hope this makes everything clearer, its very hard to explain since it took me like half a year to understand it myself ;)

关于 PhilmEs 的回答:是的,目录表的分辨率有更多影响,例如自定义操作.记住这一点,管理安装可能会导致不同的目录(例如,因为不同的序列可能包含不同的自定义操作).组件有条件,所以可能根本没有安装文件.我很确定 InstEd 也不会考虑自定义操作.

And regarding PhilmEs answer: Yes there are more influences to the resolution of the directory table, like custom actions. keeping that in mind also the administrative installation might result in different directorys (eg. because different sequence might hold different custom actions). Components have conditions so maybe a file is not installed at all. Im pretty sure InstEd doesnt take custom actions into account either.

所以是的,没有 100% 的解决方案.也许需要将所有东西混合在一起.

So yes, there is no 100% solution. Maybe a mix of everything is necessary.

这篇关于如何在 VBScript 中解析 MSI 路径?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆