Làm cách nào để thêm hành động tùy chỉnh WiX chỉ xảy ra khi gỡ cài đặt (thông qua MSI)?


160

Tôi muốn sửa đổi trình cài đặt MSI (được tạo thông qua WiX ) để xóa toàn bộ thư mục khi gỡ cài đặt.

Tôi hiểu RemoveFileRemoveFoldercác tùy chọn trong WiX, nhưng chúng không đủ mạnh để xóa đệ quy toàn bộ thư mục có nội dung được tạo sau khi cài đặt.

Tôi nhận thấy câu hỏi Stack Overflow tương tự Xóa các tệp khi gỡ cài đặt WiX , nhưng tôi tự hỏi liệu điều này có thể được thực hiện đơn giản hơn bằng cách sử dụng lệnh gọi đến một tập lệnh bó để xóa thư mục.

Đây là lần đầu tiên tôi sử dụng WiX và tôi vẫn nhận được các hành động tùy chỉnh . Điều gì sẽ là một ví dụ cơ bản về một hành động tùy chỉnh sẽ chạy một tập lệnh bó khi gỡ cài đặt?

Câu trả lời:


188

EDIT : Có lẽ nhìn vào câu trả lời ngay bên dưới .


Chủ đề này đã được đau đầu trong một thời gian dài. Cuối cùng tôi đã tìm nó ra. Có một số giải pháp trực tuyến, nhưng không có giải pháp nào thực sự hiệu quả. Và tất nhiên không có tài liệu. Vì vậy, trong biểu đồ bên dưới, có một số thuộc tính được đề xuất sử dụng và các giá trị chúng có cho các tình huống cài đặt khác nhau:

văn bản thay thế

Vì vậy, trong trường hợp của tôi, tôi muốn một CA chỉ chạy khi gỡ cài đặt - không phải nâng cấp, không sửa chữa hoặc sửa đổi. Theo bảng trên tôi đã phải sử dụng

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

Va no đa hoạt động!


25
Các giá trị trong biểu đồ đó có đúng không? Tại sao bạn cần thêm XÓA = "TẤT CẢ"? KHÔNG UPGRADINGPRODUCTCODE chỉ đúng với việc gỡ cài đặt (theo biểu đồ), vì vậy (KHÔNG NÂNG CẤP XÓA = "TẤT CẢ" dường như không cần thiết.
Todd Ropog

2
Tôi đồng ý với @ToddRopog - Ví dụ và bảng chân lý dường như không đồng ý. Điều đó có thực sự đúng không?
Tim Long

19
Bảng chân lý hơi sai. KHÔNG UPGRADINGPRODUCTCODE cũng đúng cho lần cài đặt đầu tiên
Neil

2
Điều kiện thường gặp: alekdavis.blogspot.ru/2013/05/ từ
KindDragon

1
Vui lòng xác nhận: Đã cài đặt và CÀI ĐẶT là những thứ khác nhau, chỉ Cài đặt được cài đặt bởi Windows Installer. Tôi không nghĩ rằng CÀI ĐẶT hoạt động.
Micha Wiedenmann

139

Có nhiều vấn đề với câu trả lời của yaluna , cũng như tên thuộc tính phân biệt chữ hoa chữ thường, Installedlà cách viết đúng ( INSTALLEDsẽ không hoạt động). Bảng trên phải là cái này:

nhập mô tả hình ảnh ở đây

Ngoài ra, giả sử sửa chữa đầy đủ và gỡ cài đặt các giá trị thực của các thuộc tính có thể là:

nhập mô tả hình ảnh ở đây

Các WiX Biểu Cú pháp tài liệu nói:

Trong các biểu thức này, bạn có thể sử dụng tên thuộc tính (hãy nhớ rằng chúng phân biệt chữ hoa chữ thường).

Các thuộc tính được ghi lại trong Hướng dẫn cài đặt Windows (ví dụ: Đã cài đặt )

EDIT: Hiệu chỉnh nhỏ vào bảng đầu tiên; rõ ràng "Uninstall" cũng có thể xảy ra chỉ với REMOVEcon người True.


3
XÓA cũng xuất hiện để được đặt cho Thay đổi
szx

2
Cột 'Nâng cấp', trong quá trình gỡ cài đặt phiên bản cũ hay trình tự cài đặt của phiên bản mới?
Nick Whaley

1
@NickWhaley: Tôi đã không xem xét nó một thời gian nhưng tôi tin rằng tùy chọn "Nâng cấp" chỉ khi cài đặt phiên bản lớn hơn phiên bản đã cài đặt.
ahmd0

1
@ ahmd0, tất nhiên rồi. Nhưng có một cài đặt lồng nhau xảy ra trong RemoveEx hiện Products có một bộ thuộc tính hoàn toàn khác. Đó là những gì trong cột 'Nâng cấp' của bạn. Phần còn lại của bản nâng cấp giống hệt với cột 'Cài đặt'.
Nick Whaley

1
@NickWhaley: Tùy chọn XÓA sẽ đúng với các Nâng cấp chính, tức là 1.0.0 đến 2.0.0, không phải 1.0.0 đến 1.1.0, trong khi thực hiện trình gỡ cài đặt của phiên bản trước. Để chạy Hành động tùy chỉnh trong quá trình nâng cấp chính trong các phiên bản mới, bạn sẽ cần tham khảo ActionProperty được xác định trong bảng MSI nâng cấp của mình để nâng cấp phiên bản đó. symantec.com/connect/articles/msi-upgrade-overview msdn.microsoft.com/en-us/library/aa372379%28v=vs.85%29.aspx
Chaoix

48

Bạn có thể làm điều này với một hành động tùy chỉnh. Bạn có thể thêm một sự điều chỉnh cho hành động tùy chỉnh của bạn trong <InstallExecuteSequence>:

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

Sau đó, bạn cũng sẽ phải xác định Hành động của mình trong <Product>:

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

Trong đó FileCleanerEXE là tệp nhị phân (trong trường hợp của tôi là một chương trình c ++ nhỏ thực hiện hành động tùy chỉnh) cũng được định nghĩa trong <Product>:

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

Thủ thuật thực sự cho vấn đề này là Installed AND NOT UPGRADINGPRODUCTCODEđiều kiện trên Hành động tùy chỉnh, ngoài ra hành động của bạn sẽ được chạy trên mọi nâng cấp (vì bản nâng cấp thực sự là gỡ cài đặt sau đó cài đặt lại). Mà nếu bạn đang xóa các tập tin có thể không muốn bạn muốn trong quá trình nâng cấp.

Lưu ý phụ: Tôi khuyên bạn nên khắc phục sự cố khi sử dụng chương trình C ++ để thực hiện hành động, thay vì tập lệnh bó vì sức mạnh và kiểm soát mà nó cung cấp - và bạn có thể ngăn cửa sổ "cmd prompt" nhấp nháy trong khi trình cài đặt của bạn chạy.


3
25 upvote nhưng không phải là một câu trả lời được chấp nhận. Chào mừng đến với thế giới của trình cài đặt! :)
Christopher Họa sĩ

4
Điều này không thực sự hoạt động. Khi bạn muốn thực thi một fileCleaner.exe, được cài đặt trong thư mục cài đặt của riêng bạn, đây sẽ là một vấn đề gà và trứng: Điều CustomActionnày sẽ được thực thi "After = 'InstallFinalize'". Tại thời điểm này, tất cả các tệp được xóa khỏi thư mục Cài đặt. Ngoài ra fileCleaner.exe. Vì vậy, bạn không thể thực thi nó thông qua CustomAction. Câu trả lời này đơn giản là sai. Tôi đang tự hỏi về 42 upvote!
Simon

40

Vấn đề lớn nhất với tập lệnh bó là xử lý rollback khi người dùng nhấp hủy (hoặc có lỗi xảy ra trong quá trình cài đặt của bạn). Cách chính xác để xử lý tình huống này là tạo CustomAction thêm các hàng tạm thời vào bảng RemoveFiles. Bằng cách đó, Windows Installer xử lý các trường hợp rollback cho bạn. Nó đơn giản hơn rất nhiều khi bạn nhìn thấy giải pháp.

Dù sao, để có một hành động chỉ thực hiện trong khi gỡ cài đặt, hãy thêm phần tử Điều kiện với:

REMOVE ~= "ALL"

the ~ = nói so sánh trường hợp không nhạy cảm (mặc dù tôi nghĩ TẤT CẢ luôn luôn là chữ hoa). Xem tài liệu MSI SDK về Điều kiện Cú pháp để biết thêm thông tin.

PS: Chưa bao giờ có trường hợp tôi ngồi xuống và nghĩ, "Ồ, tập tin bó sẽ là một giải pháp tốt trong gói cài đặt." Trên thực tế, việc tìm một gói cài đặt có tệp bó trong đó sẽ chỉ khuyến khích tôi trả lại sản phẩm để được hoàn lại tiền.


Tôi đã định sử dụng một tập lệnh bó và sau đó thấy phần PS. Cảm ơn vì đã cứu tôi :) Loại bỏ ~ = "TẤT CẢ" đã làm việc cho tôi.
ArNumb

12

Đây là một tập hợp các thuộc tính tôi tạo ra để sử dụng trực quan hơn so với các công cụ tích hợp. Các điều kiện dựa trên bảng chân lý được cung cấp ở trên bởi 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>

Đây là một số cách sử dụng mẫu:

  <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>

Các vấn đề:


Đây là một giải pháp tuyệt vời. Hãy nhớ cũng xem xét các điều kiện PATCH và MSIPATCHREMISE.
Garet Jax

Trong bảng chân lý của bạn, bạn có nghĩa là sử dụng PREVIOUSVERSIONSINSTALLED thay vì UPGRADINGPRODUCTCODE như được sử dụng bởi ahmd0? Tôi không thấy bất kỳ tài liệu tham khảo nào về PREVIOUSVERSIONSINSTALLED trên trang tham chiếu thuộc tính MSI ( docs.microsoft.com/en-us/windows/win32/msi/property-reference ).
Patrick

Một số vị từ cho các thuộc tính của bạn không tính đến tất cả các hàng trong bảng của ahmd0 (Đã cài đặt, REINSTALL, UPGRADINGPRODUCTCODE và XÓA). Bạn vui lòng giải thích tại sao?
Patrick

0

Tôi đã sử dụng Custom Action được mã hóa riêng trong DLL C ++ và sử dụng DLL để gọi chức năng phù hợp khi Gỡ cài đặt bằng cú pháp này:

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

Sử dụng khối mã ở trên, tôi có thể chạy bất kỳ chức năng nào được xác định trong C ++ DLL khi gỡ cài đặt. FYI, chức năng gỡ cài đặt của tôi có mã liên quan đến Xóa dữ liệu người dùng hiện tại và các mục đăng ký.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.