我真正想要做的是确定在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
和使用任何解析器看到我的字符串是否是存在的。 但我希望不那么笨重的方式存在。
需要注意的是,作为文档msilib
说,“读取.cab文件的支持尚未实现”。 和。 更一般地,该库是专门为建筑的.msi文件,而不是阅读。 还有没有别的在STDLIB会做你想要什么。
因此,有以下几种可能:
- 查找并安装另一个库,像
pycabinet
。 我对此一无所知特定库; 这只是第一个搜索命中我; 你可能想在自己的搜索。 但它宣称提供一个zipfile
的CAB文件式的API,这听起来像正是你缺少的部分。 - 使用
win32com
(如果你有pywin32
)或ctypes
(如果你是一个受虐狂)交谈的基础COM接口和/或经典内阁API(我认为这是现在已经过时,但仍然有效)。 - 使用IronPython的而不是CPython的,所以你可以使用简单的.NET接口。
因为我没有Windows中在这里,我不能对此进行测试,但这里的克里斯托弗画家写在IronPython的,而不是C#.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()
要知道,在使用Python,你必须处理Windows安装程序(COM)自动化接口。 这意味着你必须做所有的数据库连接,查询和处理自己。
如果你可以移动到C#(或者说PowerShell的),你可以利用存在于Windows安装程序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特性(真)和Python的调用它。
微星的API本身是笨重的,所以它只能是在哪里抽象躺着一个问题。 请记住,如果你只需要这几次,它可能是更容易浏览CAB文件(S)在资源管理器中手动。 (文件由文件密钥,而不是文件名保存)。
文章来源: Can I use msilib or other Python libraries to extract one file from an .msi file?