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 ファイルを読み取るためではなく、ビルドするために設計されています。そして、あなたが望むことをする標準ライブラリには他に何もありません。

したがって、いくつかの可能性があります。

  1. などの別のライブラリを見つけてインストールしますpycabinet。この特定のライブラリについては何も知りません。それは私が得た最初の検索ヒットです。おそらく自分で検索したいでしょう。しかし、それはzipfileCAB ファイル用の のような API を提供すると主張しています。
  2. win32com(持っている場合pywin32) またはctypes(マゾヒストの場合) を使用して、基礎となる COM インターフェイスおよび/または従来のキャビネット API (現在は非推奨になっていると思いますが、まだ機能します) と通信します。
  3. CPython の代わりに IronPython を使用して、より単純な .NET インターフェイスを使用できるようにします。

ここには Windows ボックスがないため、これをテストすることはできませんが、C# ではなく IronPython で記述された 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()
于 2013-03-26T01:05:19.617 に答える
1

Python を使用する場合、Windows インストーラー (COM) オートメーション インターフェイスを処理する必要があることに注意してください。これは、すべてのデータベース接続、クエリ、および処理を自分で行う必要があることを意味します。

C# (または PowerShell と言う) に移行できる場合は、Windows Installer XML (WiX) Deployment Tools Foundation (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 に答える