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


160

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

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

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

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

回答:


188

編集:おそらく現在すぐ下の答えを見てください。


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

代替テキスト

そのため、私の場合、アンインストール時にのみ実行されるCAが必要でした-アップグレードではなく、修復や変更はありません。上記の表によると、私は使用しなければなりませんでした

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

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


25
そのグラフの値は正しいですか?なぜREMOVE = "ALL"を追加する必要があるのですか?NOT UPGRADINGPRODUCTCODEは、(チャートによると)アンインストールに対してのみ当てはまるため、(NOT UPGRADINGPRODUCTCODE)AND(REMOVE = "ALL")もアンインストール時にのみ当てはまります。REMOVE = "ALL"は不要のようです。
Todd Ropog、

2
@ToddRopogに同意します-例と真理値表は一致していないようです。それは本当に正しいですか?
ティムロング

19
真理値表は少し間違っています。NOT UPGRADINGPRODUCTCODEは最初のインストールにも当てはまります
Neil


1
確認してください:インストール済みとインストール済みは異なります。インストール済みのみがWindowsインストーラーによって設定されます。INSTALLEDが機能するとは思いません。
Micha Wiedenmann、

139

yalunaの回答には複数の問題があります。また、プロパティ名は大文字と小文字が区別され、Installed正しいスペルです(機能しINSTALLEDません)。上記の表はこれであるはずです:

ここに画像の説明を入力してください

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

ここに画像の説明を入力してください

WiXの式の構文のドキュメントは言います:

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

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

編集:最初の表に対する小さな修正。明らかに「アンインストール」は、だけでも発生する可能性REMOVEがありTrueます。


3
REMOVEも変更に設定されているようです
szx '21

2
「アップグレード」列は、古いバージョンのアンインストールシーケンス中または新しいバージョンのインストールシーケンス中ですか?
Nick Whaley 2014

1
@NickWhaley:しばらく調べていませんが、「アップグレード」オプションは、すでにインストールされているバージョンよりも新しいバージョンをインストールする場合にのみあると思います。
ahmd0

1
@ ahmd0、もちろんです。しかし、まったく異なるプロパティセットを持つRemoveExistingProducts内で発生するネストされたインストールがあります。それが「アップグレード」列の内容です。アップグレードの残りの部分は、「インストール」列と同じです。
Nick Whaley

1
@NickWhaley:以前のバージョンのアンインストーラーの実行中、REMOVEオプションはメジャーアップグレード、つまり1.0.0から1.1.0ではなく1.0.0から2.0.0に当てはまります。新しいバージョンのインストールでメジャーアップグレード中にカスタムアクションを実行するには、そのバージョンアップグレードのアップグレードMSIテーブルで定義されているActionPropertyを参照する必要があります。symantec.com/connect/articles/msi-upgrade-overview msdn.microsoft.com/en-us/library/aa372379%28v=vs.85%29.aspx
Chaoix

48

カスタムアクションでこれを行うことができます。以下のカスタムアクションに参照を追加できます<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 ++プログラムのようなものを使用してアクションを実行するという問題に対処することをお勧めします。これにより、スクリプトの能力と制御が向上し、「cmdプロンプト」ウィンドウが点滅しないようにすることができます。インストーラーが実行されます。


3
25賛成投票。ただし、承認された回答ではありません。インストーラーの世界へようこそ!:)
クリストファーペインター

4
これは実際には機能しません。独自のインストールフォルダーにインストールされているfileCleaner.exeを実行する場合、これは鶏と卵の問題にCustomActionなります。「After = 'InstallFinalize'」が実行されます。この時点で、すべてのファイルがインストールフォルダから削除されます。また、fileCleaner.exe。したがって、CustomActionを介してそれを実行することはできません。この答えは間違っています。42の賛成票について疑問に思っています。
Simon

40

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

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

REMOVE ~= "ALL"

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

PS:私が座って「ああ、バッチファイルがインストールパッケージの良い解決策になるだろう」と思った例はこれまでありませんでした。実際、バッチファイルが含まれているインストールパッケージを見つけても、製品を返品して払い戻しを受けることはできます。


バッチスクリプトを使用しようとしたところ、PSセクションが表示されました。私を保存してくれてありがとう:)削除〜= "ALL"がうまくいきました。
ArNumb

12

以下は、組み込みのものよりも直感的に使用できるようにした一連のプロパティです。条件は、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>

問題:


これは素晴らしいソリューションです。PATCHおよびMSIPATCHREMOVE条件も考慮することを忘れないでください。
Garet Jax

真理値表では、ahmd0で使用されるUPGRADINGPRODUCTCODEではなくPREVIOUSVERSIONSINSTALLEDを使用することを意味しましたか?MSIプロパティリファレンスページ(docs.microsoft.com/en-us/windows/win32/msi/property-reference)にPREVIOUSVERSIONSINSTALLEDへの参照が表示されません。
Patrick

プロパティのいくつかの述語は、ahmd0のテーブルのすべての行を考慮していません(Installed、REINSTALL、UPGRADINGPRODUCTCODE、およびREMOVE)。理由を教えてください。
Patrick

0

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.