0

我真正想做的是确定 MSI 中的特定文件是否存在并包含特定字符串。

我目前的想法是运行:

 db = msilib.OpenDatabase('c:\Temp\myfile.msi',1)
 query = "select * from File"
 view = db.OpenView(query)
 view.Execute(None)
 cur_record = view.Fetch()     # do this until I get the record I want
 print cur_record.GetString(3) # do stuff with this value

然后如果它在那里,使用提取所有文件

msiexec /a c:\Temp\myfile.msi /qn TARGETDIR=c:\foo

并使用任何解析器来查看我的字符串是否存在。但我希望存在一种不那么笨重的方式。

4

3 回答 3

3

请注意,正如文档msilib所说,“当前未实现对读取 .cab 文件的支持”。和。更一般地说,该库旨在构建 .msi 文件,而不是读取它们。stdlib 中没有其他东西可以满足您的需求。

所以,有几种可能:

  1. 查找并安装另一个库,例如pycabinet. 我对这个特定的图书馆一无所知。这只是我得到的第一个搜索结果;你可能想自己搜索。但它声称zipfile为 CAB 文件提供了一个类似的 API,这听起来正是你所缺少的部分。
  2. 使用win32com(如果你有pywin32)或ctypes(如果你是受虐狂)与底层的 COM 接口和/或经典的 Cabinet API(我认为现在已弃用,但仍然有效)对话。
  3. 使用 IronPython 而不是 CPython,因此您可以使用更简单的 .NET 接口。

因为我这里没有 Windows 盒子,所以我无法对此进行测试,但这里是 Christopher Painter 的 .NET 解决方案的草图,它是用 IronPython 而不是 C# 编写的:

import clr
clr.AddReference('Microsoft.Deployment.WindowsInstaller')
clr.AddReference('Microsoft.Deployment.WindowsInstaller.Package')
from Microsoft.Deployment.WindowsInstaller import *
from Microsoft.Deployment.WindowsInstaller.Package import *

def FindAndExtractFiles(packagePath, longFileName):
    with InstallPackage(packagePath, DatabaseOpenMode.ReadOnly) as installPackage:
        if installPackage.FindFiles(longFileName).Count() > 0:
            installPackage.ExtractFiles()
于 2013-03-26T01:05:19.617 回答
1

意识到在使用 Python 时,您必须处理 Windows Installer (COM) 自动化接口。这意味着您必须自己完成所有数据库连接、查询和处理。

如果您可以迁移到 C#(或者说 PowerShell),您可以利用 Windows Installer XML (WiX) 部署工具基础 (DTF) 中存在的一些更高级别的类。

using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Deployment.WindowsInstaller.Package;

static void FindAndExtractFiles(string packagePath, string longFileName)
{
    using (var installPackage = new InstallPackage(packagePath, DatabaseOpenMode.ReadOnly))
    {
        if(installPackage.FindFiles(longFileName).Count() > 0 )
            installPackage.ExtractFiles();
    }
}

您也可以将其写为 ComVisible(True) 并从 Python 调用它。

于 2013-03-20T19:22:58.037 回答
0

MSI API 本身就很笨重,所以这只是抽象所在的问题。请记住,如果您只需要几次,在资源管理器中手动浏览 cab 文件可能会更容易。(文件按文件键而不是文件名存储)。

于 2013-03-21T12:04:44.307 回答