web-dev-qa-db-ja.com

アンインストール時にのみ発生するWiXカスタムアクションを追加する方法(MSI経由)

MSIインストーラー( WiX で作成)を変更して、アンインストール時にディレクトリ全体を削除したいと思います。

WiXのRemoveFileおよびRemoveFolderオプションは理解していますが、これらは、インストール後に作成されたコンテンツを含むフォルダー全体を再帰的に削除するほど堅牢ではありません。

同様のスタックオーバーフローの質問WiXのアンインストール時にファイルを削除するに気付きましたが、これをもっと簡単に使用できるかどうか疑問に思いましたフォルダーを削除するバッチスクリプトの呼び出し。

WiXを使用するのはこれが初めてであり、まだ カスタムアクション がハングしています。アンインストール時にバッチスクリプトを実行するカスタムアクションの基本的な例は何ですか?

151
Zack

EDIT:おそらくすぐ下の答えを見てください。


このトピックは長い間頭痛の種でした。私はついにそれを理解しました。オンラインでいくつかのソリューションがありますが、どれも実際には機能しません。そしてもちろん、ドキュメントはありません。そのため、下のグラフには、使用が推奨されるいくつかのプロパティと、さまざまなインストールシナリオでの値があります。

alt text

したがって、私の場合、アンインストール時にのみ実行されるCAが必要でした。アップグレード、修復、または修正ではありません。上記の表によると、

<Custom Action='CA_ID' Before='other_CA_ID'>
        (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>

そしてそれはうまくいきました!

183
yaluna

yaluna's answer には複数の問題があり、プロパティ名でも大文字と小文字が区別されます。Installedは正しいスペルです(INSTALLEDは機能しません)。上記の表は次のようになっているはずです。

enter image description here

また、完全な修復とアンインストールを想定して、プロパティの実際の値は次のようになります。

enter image description here

WiX Expression Syntax ドキュメントには次のように書かれています:

これらの式では、プロパティ名を使用できます(大文字と小文字が区別されることに注意してください)。

プロパティは、Windowsインストーラーガイドに記載されています(例: Installed

編集:最初のテーブルの小さな修正。明らかに「アンインストール」は、REMOVETrueである場合にも発生します。

126
ahmd0

これを行うには、カスタムアクションを使用します。 <InstallExecuteSequence>の下のカスタムアクションに参照を追加できます。

<InstallExecuteSequence>
...
  <Custom Action="FileCleaner" After='InstallFinalize'>
          Installed AND NOT UPGRADINGPRODUCTCODE</Custom>

次に、<Product>の下でアクションを定義する必要があります。

<Product> 
...
  <CustomAction Id='FileCleaner' BinaryKey='FileCleanerEXE' 
                ExeCommand='' Return='asyncNoWait'  />

FileCleanerEXEはバイナリ(私の場合はカスタムアクションを実行する小さなc ++プログラム)であり、<Product>の下でも定義されています。

<Product> 
...
  <Binary Id="FileCleanerEXE" SourceFile="path\to\fileCleaner.exe" />

これに対する本当のトリックは、カスタムアクションのInstalled AND NOT UPGRADINGPRODUCTCODE条件であり、アクションはアップグレードごとに実行されます(アップグレードは実際にはアンインストールで再インストールなので)。ファイルを削除する場合は、おそらくアップグレード中に望んでいないでしょう。

補足:バッチスクリプトではなく、C++プログラムのようなものを使用してアクションを実行するというトラブルを経験することをお勧めします。インストーラーが実行されます。

48
csexton

バッチスクリプトの最大の問題は、ユーザーが[キャンセル]をクリックしたとき(またはインストール中に問題が発生したとき)にロールバックを処理することです。このシナリオを処理する正しい方法は、RemoveFilesテーブルに一時行を追加するCustomActionを作成することです。このようにして、Windowsインストーラーがロールバックケースを処理します。解決策を見ると、非常に簡単です。

とにかく、アンインストール中にのみアクションを実行するには、次の条件要素を追加します。

REMOVE ~= "ALL"

〜=は大文字と小文字を区別せずに比較します(ALLは常にuppercaesdであると思いますが)。詳細については、 条件構文に関するMSI SDKドキュメント を参照してください。

PS:「ああ、バッチファイルがインストールパッケージに適したソリューションになる」と考えて考えたことはありませんでした。実際、バッチファイルが含まれているインストールパッケージを見つけることは、払い戻しのために製品を返品することを促すだけです。

39
Rob Mensching

これは、組み込みのものよりも直感的に使用できるようにした一連のプロパティです。条件は、ahmd0によって上記で提供された真理値表に基づいています。

<!-- truth table for installer varables (install vs uninstall vs repair vs upgrade) https://stackoverflow.com/a/17608049/1721136 -->
 <SetProperty Id="_INSTALL"   After="FindRelatedProducts" Value="1"><![CDATA[Installed="" AND PREVIOUSVERSIONSINSTALLED=""]]></SetProperty>
 <SetProperty Id="_UNINSTALL" After="FindRelatedProducts" Value="1"><![CDATA[PREVIOUSVERSIONSINSTALLED="" AND REMOVE="ALL"]]></SetProperty>
 <SetProperty Id="_CHANGE"    After="FindRelatedProducts" Value="1"><![CDATA[Installed<>"" AND REINSTALL="" AND PREVIOUSVERSIONSINSTALLED<>"" AND REMOVE=""]]></SetProperty>
 <SetProperty Id="_REPAIR"    After="FindRelatedProducts" Value="1"><![CDATA[REINSTALL<>""]]></SetProperty>
 <SetProperty Id="_UPGRADE"   After="FindRelatedProducts" Value="1"><![CDATA[PREVIOUSVERSIONSINSTALLED<>"" ]]></SetProperty>

使用例は次のとおりです。

  <Custom Action="CaptureExistingLocalSettingsValues" After="InstallInitialize">NOT _UNINSTALL</Custom>
  <Custom Action="GetConfigXmlToPersistFromCmdLineArgs" After="InstallInitialize">_INSTALL OR _UPGRADE</Custom>
  <Custom Action="ForgetProperties" Before="InstallFinalize">_UNINSTALL OR _UPGRADE</Custom>
  <Custom Action="SetInstallCustomConfigSettingsArgs" Before="InstallCustomConfigSettings">NOT _UNINSTALL</Custom>
  <Custom Action="InstallCustomConfigSettings" Before="InstallFinalize">NOT _UNINSTALL</Custom>

問題点:

6
Bill Tarbell

C++ DLLで個別にコーディングされたカスタムアクションを使用し、DLLを使用して、この構文を使用したアンインストール時に適切な関数を呼び出しました。

<CustomAction Id="Uninstall" BinaryKey="Dll_Name" 
              DllEntry="Function_Name" Execute="deferred" />

上記のコードブロックを使用して、アンインストール時にC++ DLLで定義された関数を実行できました。参考までに、私のアンインストール機能には、現在のユーザーデータとレジストリエントリの消去に関するコードがありました。

0
Sid