我真正想要做的是确定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
并使用任何解析器来查看我的字符串是否存在。但我希望存在一种不那么笨重的方式。
答案 0 :(得分:3)
请注意,正如msilib
的文档所说,“目前尚未实现”支持读取.cab文件“。和。更一般地说,该库设计用于构建.msi文件,而不是读取它们。 stdlib中没有任何其他东西可以做你想做的事。
所以,有几种可能性:
pycabinet
。我对这个特定的图书馆一无所知;这只是我得到的第一次搜索;你可能想自己搜索。但它声称为CAB文件提供了类似zipfile
的API,这听起来就像你缺少的部分。win32com
(如果您有pywin32
)或ctypes
(如果您是受虐狂)与基础COM接口和/或经典Cabinet API进行通信(我认为现在已弃用,但仍然有效。)由于我这里没有Windows框,我无法对此进行测试,但这里是使用IronPython而不是C#编写的Christopher Painter .NET解决方案的草图:
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()
答案 1 :(得分:1)
意识到在使用Python时你必须处理Windows Installer(COM)Automation接口。这意味着您必须自己进行所有数据库连接,查询和处理。
如果您可以转到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调用它。
答案 2 :(得分:0)
MSI API本质上是笨重的,所以它只是抽象所在的问题。请记住,如果您只需要几次,则可以更轻松地在资源管理器中手动浏览cab文件。 (文件由文件密钥而不是文件名存储。)