12

必要なのは、マージモジュール(.msm)からディスクにファイルを抽出できるコマンドラインツールだけです。言い換えると、MSIで可能なのと同じ「管理インストール」機能が必要です。

msiexec / a myProduct.msi TARGETDIR = "C:\ myInstallation" / qn

上記はmsiでのみ機能します(私が知る限り)。したがって、マージモジュールで同じ効果を得るには、msidb.exeとorca.exeを試しています。orcaのドキュメントには次のように記載されています。

多くのマージモジュールオプションは、コマンドラインから指定できます。

マージモジュールからのファイルの抽出

Orcaは、マージモジュールに含まれるファイルを抽出するための3つの異なる方法をサポートしています。Orcaは、個々のCABファイルを抽出し、ファイルをモジュールツリーに抽出し、ターゲットデータベースにマージされた後、ファイルをソースイメージに抽出できます...

ファイルの抽出

マージモジュールから個々のファイルを抽出するには、

... -x ...コマンドラインのオプション。ここで、は新しいディレクトリツリーへの目的のパスです。

指定されたパスは、抽出されたファイルのルートパスとして使用されます。すべてのファイルは、モジュールに埋め込まれたCABファイルから抽出され、指定されたパスに配置されます。抽出されたファイルのディレクトリレイアウトは、マージモジュールのディレクトリツリーに基づいています。

それは私が必要なもののように聞こえます。しかし、私が試してみると、orcaは(指定したmsmに関する情報を含む)エディターを開くだけで、何もしません。私はさまざまなコマンドラインを試しましたが、通常は次のようになります。

orca -x theDirectory theModule.msm

空のフォルダとして「theDirectory」を使用します。私が言ったように-それは何もしませんでした。

次に、msidbを試しました。ここで、いくつかの試行は次のようになります。

msidb -d theModule.msm-w{ストレージ}

msidb -d theModule.msm -x MergeModule.CABinet

最初のケースでは、{storage}に何を入れるべきかわかりません。2番目のケースでは、リテラル文字列「MergeModule.CABinet」が必要であることがわかります(これは予約済みの名前です)。ただし、抽出されたキャビネットは、ファイル階層または「通常の」ファイル名を保持しません。だから私は自分の目的のためにそれを使うことができません。

誰かが私がコマンドラインオプションで間違っていることを説明できますか?これを行うことができる他のツールはありますか?

4

5 に答える 5

14

WiXに含まれている逆コンパイラ ツール( Darkと呼ばれる) を使用して、マージ モジュールを逆コンパイルし、ファイルを抽出できます。

dark.exe myMergeModule.msm -x "path_to_extracted_files"

ファイルは、-x パラメータで指定されたパスに抽出されます。

注:ファイルは、インストール データベースのファイル テーブルで指定された名前を使用して抽出されます。これは、ファイルが実際にインストールされるときに実際に使用されるファイル名ではない場合があります。実際のファイル名を使用してファイルを抽出する必要がある場合は、この質問に対する私の他の回答を参照してください: Extracting files from merge module

于 2012-07-27T15:08:39.273 に答える
5

空の msi を作成し、Orca を使用してモジュールを msi にマージし、ファイルを抽出することでこれを行う必要がありました。

  1. 空の .msi を作成します。私はWiX 3.6を使用して .msi を作成しました。以下は最小限のソースです。「blank.msi」と名付けました。

    <?xml version="1.0" encoding="UTF-8"?>
    <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
        <Product Id="*" Name="blank" Language="1033" Version="1.0.0.0" Manufacturer="blank" UpgradeCode="298878d0-5e7b-4b2e-84f9-45bb66541b10">
            <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
    
            <MediaTemplate />
    
            <Directory Id="TARGETDIR" Name="SourceDir">
                <Directory Id="ProgramFilesFolder"/>
            </Directory>
    
            <ComponentGroup Id="ProductComponents" Directory="ProgramFilesFolder" />
    
            <Feature Id="ProductFeature" Title="blank" Level="1">
                <ComponentGroupRef Id="ProductComponents" />
            </Feature>
         </Product>
    </Wix>
    
  2. Orcaを使用して、マージ モジュールからファイルを抽出します。

    orca -m "myModule.msm" -f ProductFeature -x .\xdir blank.msi
    

ファイルは -x パラメータで指定されたディレクトリ (この場合は.\xdir ) に抽出されます。

-f パラメータ「ProductFeature」の値は、上記の msi ファイルで指定された機能の名前と一致することに注意してください。

于 2012-07-27T14:59:01.357 に答える
1

WiXの DeploymentToolsFoundation クラス ライブラリには、ExtractFiles() メソッドを含む InstallPackage クラスがあり、必要なことだけを実行する必要がありますが、マージ モジュールでは失敗します。これはバグのようです。

DTF を使用してマージ モジュールの CAB にアクセスする次の PowerShell スクリプトは、必要な処理を実行する必要があります。スクリプトが少し不安定な場合はお詫びします。私は PowerShell を初めて使用します。

[Reflection.Assembly]::LoadFrom("[InsertPath]\Microsoft.Deployment.WindowsInstaller.dll")

function ExtractMSM([string]$file, [string]$targetDir)
{
    write-host "Extracting files from merge module: "$file

    if(![IO.Directory]::Exists($targetDir)) { new-item -type directory -path $targetDir }

    $cabFile = join-path $targetDir "temp.cab"
    if([IO.File]::Exists($cabFile)) { remove-item $cabFile }

    $db = new-object Microsoft.Deployment.WindowsInstaller.DataBase($file, [Microsoft.Deployment.WindowsInstaller.DataBaseOpenMode]::ReadOnly)
    $view = $db.OpenView("SELECT `Name`,`Data` FROM _Streams WHERE `Name`= 'MergeModule.CABinet'")
    $view.Execute()
    $record = $view.Fetch()
    $record.GetStream(2, $cabFile)
    $view.Dispose()

    expand -F:* $cabFile $targetDir

    remove-item $cabFile

    $extractedFiles = get-childitem $targetDir
    $hashFiles = @{}
    foreach($extracted in $extractedFiles)
    {
        try
        {
            $longName = $db.ExecuteScalar("SELECT `FileName` FROM `File` WHERE `File`='{0}'", $extracted.Name) 
        }
        catch 
        {
            write-host "$($extracted.Name) is not in the MSM file"
        }

        if($longName)
        {
            $longName = $LongName.SubString($LongName.IndexOf("|") + 1)
            Write-host $longName

            #There are duplicates in the 
            if($hashFiles.Contains($longName))
            {
                write-host "Removing duplicate of $longName"
                remove-item $extracted.FullName
            }
            else
            {
                write-host "Rename $($extracted.Name) to $longName"
                $hashFiles[$longName] = $extracted
                $targetFilePath = join-path $targetDir $longName
                if([IO.File]::Exists($targetFilePath)) {remove-item $targetFilePath}
                rename-item $extracted.FullName -NewName $longName    
            }
        }
    }
    $db.Dispose()
}
于 2010-12-16T09:32:55.243 に答える
1

私は同様の問題を抱えていましたが、別の方向から取り組みました。

以前のバージョンの Visual Studio に付属していた InstallSheild Express をインストールし、新しいプロジェクトを作成しましたが、必要な MSM ファイルのみを追加しました。

新しいインストールをコンパイルして実行した後、MSM ファイルに含まれるファイルを取得できました。

于 2012-05-10T09:08:06.587 に答える
0

MSI2XML

于 2010-04-23T21:36:42.027 に答える