WIX Toolset を使用して MSI インストーラーを作成しました。また、テーマやダイアログなどのユーザー固有のファイルに従って、インストーラーを動的にカスタマイズする必要があります。このリンクを使用してAdd Cabinet File to Installer を追加しまし たが、読めません。キャビネット ファイルとそのファイル (カスタマイズ ファイル) を読むのに最適な場所を知りたいです。これをカスタム アクションで行うべきでしょうか、それともどこで行うのが最適でしょうか? また、このタスクを達成するために従うことができるサンプル コードが必要ですか? 注:- キャビネット ファイルには、多くのファイル (txt ファイル、画像など) が含まれます。
1 に答える
あなたがそのリンクをたどったので(それでも私自身の質問に)、メディアIDを持つ新しいキャビネットファイルとしてmsiに埋め込まれたファイルがあると思います
警告: この返信のコードは、今のところすべてテストされていません
msi は基本的に単なるデータベースであり、SQL のようなステートメントを使用してクエリを実行できることに注意してください。cab ファイルは、データベースの _Streams テーブルに埋め込まれており、元の cab ファイル形式に抽出できます。
これは、ORCA と 7zip を使用して確認できます。
あなたが言及したSOの質問に対する解決策は、ファイルを「置き換える」ように設計されました。そのため、msi ビルドでダミー ファイルが使用され、wix で配置が構成されました。次に、msi のビルド後、ファイル テーブルが変更され、wix によって生成された元の cab ファイルから挿入された新しい cab ファイルへの参照が変更されました。このように、ダミー ファイルは孤立していますが、まだ msi に埋め込まれています。
このアプローチは、ユーザーごとにカスタマイズされるファイルがわかっている場合、およびカスタマイズとは関係なく、すべてのユーザーが同じフォルダー/ファイル構造を持つ場合に適しています。
そのソリューションをコピーするだけではないため、ユーザーごとに異なる数のファイル、またはユーザーごとに異なるフォルダー構造があると思います。これを実現するには、いくつかの msi テーブルの編集が必要です。
ディレクトリ テーブル: Wix 設定でディレクトリが定義されていない場合は、このテーブルにディレクトリを作成する必要があります。
次のようにして、新しいディレクトリを挿入できるようにする必要があります。
string query = "INSERT INTO `Directory` (`Directory`, `Directory_Parent`, `DefaultDir`) ";
query += "VALUES ('" + The_Directory_ID + "', '" + The_Parents_ID + "', '" + FolderName + ")";
pkg.Execute(query);
ここから先は、新しい cab ファイル内のすべてのファイルに対してすべてを繰り返す必要があります
** 成分表 **
msiexec でインストール/アンインストールできるように、ファイルを制御するコンポーネントを作成する必要があります。
string query = "INSERT INTO `Component` (`Component`, `ComponentId`, `Directory_`, `Attributes`, `Condition`, `KeyPath`) ";
query += "VALUES ('" + The_new_files_name_or_Similar + "', '{" + FileGUID + "}', '" + The_Directory_ID + "0, \"\", "+ A_FILE_ID +" )";
pkg.Execute(query);
どこ:
- FileGUID は
Guid.NewGuid()..を使用して生成できます。 - A_FILE_ID はファイル名にすることができます。wix が MSI を生成した場合、他のすべては通常「FileID##」によって参照されるため、おそらくうまくいくでしょう。それ以外の場合は、まだファイル テーブルにない、使用できる FileID を決定する必要があります。 ..
CreateFolder テーブル: 通常、空のフォルダーを作成する必要がある場合にのみ必要です。readme ファイルなどをフォルダーにダンプできるため、ここでは無視します。
ファイル テーブル このテーブルは、msiexec に、msi 内のファイルの場所とファイルのバージョンを伝えます。これにより、コピー、更新、無視などの必要があるかどうかがわかります。
シーケンス番号は、ファイルの場所を msi に伝えるために使用され、メディア テーブルはシーケンスを cab ファイルまたは外部メディアに関連付けます。
このコードは、 , ステートメントへの単なる挿入でもあります。
- ファイル: A_FILE_ID
- コンポーネント: The_new_files_name_or_Similar
- ファイル名:ファイル名 (インストール時)
- FileSize:ファイル サイズ (バイト単位) です...
- バージョン:ファイルにバージョン番号がある場合は追加し、そうでない場合は空白のままにします。ファイルのバージョンを取得する方法は、ファイルの種類によって異なります。
- 言語:これはファイルの言語バージョンで、通常は 1033 ですが、不明な場合は空白のままにできます..
- 属性:これは、メディア ファイル (キャビネット) が埋め込まれているか、外部にあるか、またはファイルが外部にあるかなどによって異なります.msi の他のすべてのものと同じ番号を使用すると、多くの場合問題ありません。ビルド後にキャビネット ファイルを埋め込むときは、常に 512 を使用してきました。
そして、後で使用する必要がある魔法の部分:
- シーケンス:ファイル テーブルで既に見つかった最大のシーケンス値を取得し、それをインクリメントする必要があります。
FeatureComponent テーブル このテーブルは、これを機能ツリーに追加するために使用され、ユーザーがこの機能を追加または削除できるようにします。すべてのコンポーネントは機能に属している必要があります。
- Feature_このコンポーネントをインストールする機能。あなたは新しいものを作るかもしれませんし、しないかもしれません。既存のものを使用することをお勧めします!
- Component_The_new_files_name_or_Similar _
メディア テーブル 参照したコードは、キャビネット ファイルを msi に追加し、メディア テーブルにエントリを作成します。
IList<int> sequences = pkg.ExecuteIntegerQuery("SELECT `LastSequence` FROM `Media` ORDER BY `LastSequence`");
lastIndex = sequences.Count - 1;
int LastSequence = sequences.ElementAt(lastIndex) + numberOfFilesToAdd;
query = "INSERT INTO `Media` (`DiskId`, `LastSequence`, `Cabinet`) VALUES (" + DiskId.ToString() + "," + LastSequence.ToString() + ",'#" + mediaCabinet + "')";
pkg.Execute(query);
したがって、これはすでに設定されているはずです。他の誰かがこの回答に出くわした場合は、関連するスニペットをここにコピーして、新しい cab ファイルのシーケンス番号がどのように作成されるかを示します。
そのため、ファイル テーブルのシーケンス番号は、msi に既にあったものよりも大きくなりますが、既に追加した新しいメディアにあるものよりも小さくなっています。
注: cab ファイル内のファイルがシーケンス番号と同じ順序であることが非常に重要です。そうしないと、msiexec がファイルを見つけられないというエラーをスローする可能性があります。