Xóa tệp khi gỡ cài đặt WiX


84

Khi gỡ cài đặt ứng dụng của mình, tôi muốn định cấu hình thiết lập Wix để xóa tất cả các tệp đã được thêm vào sau khi cài đặt ban đầu . Có vẻ như trình gỡ cài đặt chỉ loại bỏ các thư mục và tệp đã được cài đặt ban đầu khỏi tệp MSI và nó để lại mọi thứ khác đã được thêm sau đó trong thư mục ứng dụng. Nói cách khác, tôi muốn xóa thư mục khi gỡ cài đặt. Làm thế nào để làm điều đó?

Câu trả lời:


83

Sử dụng phần tử RemoveFile với On = " uninstall ". Đây là một ví dụ:

<Directory Id="CommonAppDataFolder" Name="CommonAppDataFolder">
  <Directory Id="MyAppFolder" Name="My">
    <Component Id="MyAppFolder" Guid="*">
      <CreateFolder />
      <RemoveFile Id="PurgeAppFolder" Name="*.*" On="uninstall" />
    </Component>
  </Directory>
</Directory>

Cập nhật

Nó không hoạt động 100%. Nó đã xóa các tệp, tuy nhiên không có thư mục bổ sung nào - những thư mục được tạo sau khi cài đặt - bị xóa. Bất kỳ suy nghĩ về điều đó? - pribeiro

Rất tiếc, Windows Installer không hỗ trợ xóa thư mục bằng thư mục con. Trong trường hợp này, bạn phải dùng đến hành động tùy chỉnh. Hoặc, nếu bạn biết thư mục con là gì, hãy tạo một loạt các phần tử RemoveFolder và RemoveFile.


1
Cảm ơn Pavel. Tuy nhiên nó không hoạt động 100%. Nó đã xóa các tệp, tuy nhiên không có thư mục bổ sung nào - những thư mục được tạo sau khi cài đặt - bị xóa. Bất kỳ suy nghĩ về điều đó?
pribeiro 22/10/08

Ồ, cả các tệp trong các thư mục đó đều không bị xóa.
pribeiro 22/10/08

Khi bạn giữ các tệp (ví dụ: tệp cấu hình) trong 'MyAppFolder' trên Bản nâng cấp chính, bạn sẽ gặp sự cố với cách tiếp cận này. Tất cả các tệp sẽ bị xóa bằng bản Nâng cấp.
Simon

1
Mã của bạn có thể tạo Thư mục trong MyAppFolder không? Khi tôi thêm một thư mục sau khi </Component>tôi có một biên soạn thất bạiFound orphaned Component 'MyAppFolder'.
A.Pissicat

2
@PhilipRego Xem msdn.microsoft.com/en-us/library/windows/desktop/aa367992.aspx để biết tài liệu CommonAppDataFolder.
Pavel Chuchuva

30

Sử dụng RemoveFolderExphần tử từ tiện ích mở rộng Util trong WiX.
Với cách tiếp cận này, tất cả các thư mục con cũng bị loại bỏ (trái ngược với việc sử dụng RemoveFilephần tử trực tiếp ). Phần tử này thêm các hàng tạm thời vào RemoveFileRemoveFolderbảng trong cơ sở dữ liệu MSI.


2
Cảnh báo: Khi sử dụng RemoveFolderEx on = "uninstall", nó cũng sẽ xóa thư mục khi nâng cấp (Wix 3.9). Hành vi tương tự trên RemoveFileRemoveFolder. Nếu bạn muốn giữ tệp khi nâng cấp, bạn không thể sử dụng tất cả các phương pháp này.
Simon

@Simon bạn sẽ đề xuất phương pháp nào nếu bạn muốn giữ các tệp trên bản nâng cấp?
Bijington

@Bijington: Khi bạn muốn giữ các tệp cụ thể trong thư mục cài đặt của mình khi nâng cấp, sau đó sử dụng một hành động tùy chỉnh thực thi mã tùy chỉnh (ví dụ: c # write HandleSetup.exe). Mã tùy chỉnh cung cấp tệp của bạn khi cài đặt, giữ cho tệp của bạn được nâng cấp và xóa tệp khi gỡ cài đặt.
Simon

@Simon cảm ơn, tôi có thể phải xem xét cách tiếp cận đó mặc dù phương pháp này hiện đang hoạt động: stackoverflow.com/a/21383113/32348
Bijington

13

Để làm điều này, tôi chỉ cần tạo một hành động tùy chỉnh được gọi khi gỡ cài đặt.

Mã WiX sẽ giống như sau:

<Binary Id="InstallUtil" src="InstallUtilLib.dll" />

<CustomAction Id="DIRCA_TARGETDIR" Return="check" Execute="firstSequence" Property="TARGETDIR" Value="[ProgramFilesFolder][Manufacturer]\[ProductName]" />
<CustomAction Id="Uninstall" BinaryKey="InstallUtil" DllEntry="ManagedInstall" Execute="deferred" />
<CustomAction Id="UninstallSetProp" Property="Uninstall" Value="/installtype=notransaction /action=uninstall /LogFile= /targetDir=&quot;[TARGETDIR]\Bin&quot; &quot;[#InstallerCustomActionsDLL]&quot; &quot;[#InstallerCustomActionsDLLCONFIG]&quot;" />

<Directory Id="BinFolder" Name="Bin" >
    <Component Id="InstallerCustomActions" Guid="*">
        <File Id="InstallerCustomActionsDLL" Name="SetupCA.dll" LongName="InstallerCustomActions.dll" src="InstallerCustomActions.dll" Vital="yes" KeyPath="yes" DiskId="1" Compressed="no" />
        <File Id="InstallerCustomActionsDLLCONFIG" Name="SetupCA.con" LongName="InstallerCustomActions.dll.Config" src="InstallerCustomActions.dll.Config" Vital="yes" DiskId="1" />
    </Component>
</Directory>

<Feature Id="Complete" Level="1" ConfigurableDirectory="TARGETDIR">
    <ComponentRef Id="InstallerCustomActions" />
</Feature>

<InstallExecuteSequence>
    <Custom Action="UninstallSetProp" After="MsiUnpublishAssemblies">$InstallerCustomActions=2</Custom>
    <Custom Action="Uninstall" After="UninstallSetProp">$InstallerCustomActions=2</Custom>
</InstallExecuteSequence>

Mã cho phương thức OnBeforeUninstall trong InstallerCustomActions.DLL sẽ giống như thế này (trong VB).

Protected Overrides Sub OnBeforeUninstall(ByVal savedState As System.Collections.IDictionary)
    MyBase.OnBeforeUninstall(savedState)

    Try
        Dim CommonAppData As String = Me.Context.Parameters("CommonAppData")
        If CommonAppData.StartsWith("\") And Not CommonAppData.StartsWith("\\") Then
            CommonAppData = "\" + CommonAppData
        End If
        Dim targetDir As String = Me.Context.Parameters("targetDir")
        If targetDir.StartsWith("\") And Not targetDir.StartsWith("\\") Then
            targetDir = "\" + targetDir
        End If

        DeleteFile("<filename.extension>", targetDir) 'delete from bin directory
        DeleteDirectory("*.*", "<DirectoryName>") 'delete any extra directories created by program
    Catch
    End Try
End Sub

Private Sub DeleteFile(ByVal searchPattern As String, ByVal deleteDir As String)
    Try
        For Each fileName As String In Directory.GetFiles(deleteDir, searchPattern)
            File.Delete(fileName)
        Next
    Catch
    End Try
End Sub

Private Sub DeleteDirectory(ByVal searchPattern As String, ByVal deleteDir As String)
    Try
        For Each dirName As String In Directory.GetDirectories(deleteDir, searchPattern)
            Directory.Delete(dirName)
        Next
    Catch
    End Try
End Sub

11

Đây là một biến thể theo đề xuất của @ tronda. Tôi đang xóa một tệp "install.log" được tạo bởi một Hành động tùy chỉnh khác, trong khi Gỡ cài đặt:

<Product>
    <CustomAction Id="Cleanup_logfile" Directory="INSTALLFOLDER"
    ExeCommand="cmd /C &quot;del install.log&quot;"
    Execute="deferred" Return="ignore" HideTarget="no" Impersonate="no" />

    <InstallExecuteSequence>
      <Custom Action="Cleanup_logfile" Before="RemoveFiles" >
        REMOVE="ALL"
      </Custom>
    </InstallExecuteSequence>
</Product>

Theo như tôi hiểu, tôi không thể sử dụng "RemoveFile" vì tệp này được tạo sau khi cài đặt và không phải là một phần của Nhóm thành phần.


4
Tôi đã sử dụng giải pháp này, với một số thay đổi để xóa toàn bộ thư mục: ExeCommand = "cmd / C RD & quot; [INSTALLFOLDER] & quot; / s / q"
Dennis

@Dennis làm thế nào để xóa INSTALLFOLDER, trên win 10 thì bị xóa nhưng trên Windows server 2012 thì không.
eomeroff

Giải pháp tuyệt vời. Cảm ơn!
Yurii Komarnytskyi 14/09/17

Tôi đã thử một số cách - người ta sẽ không nghĩ rằng việc xóa một tệp duy nhất trong quá trình gỡ cài đặt lại khó đến vậy. Điều này đã làm việc cho tôi mặc dù - cảm ơn!
Lucky Luke

7

Đây sẽ là câu trả lời đầy đủ hơn cho đề xuất @Pavel , đối với tôi, nó hoạt động 100%:

<Fragment Id="FolderUninstall">
    <?define RegDir="SYSTEM\ControlSet001\services\[Manufacturer]:[ProductName]"?>
    <?define RegValueName="InstallDir"?>
    <Property Id="INSTALLFOLDER">
        <RegistrySearch Root="HKLM" Key="$(var.RegDir)" Type="raw" 
                  Id="APPLICATIONFOLDER_REGSEARCH" Name="$(var.RegValueName)" />
    </Property>

    <DirectoryRef Id='INSTALLFOLDER'>
        <Component Id="UninstallFolder" Guid="*">
            <CreateFolder Directory="INSTALLFOLDER"/>
            <util:RemoveFolderEx Property="INSTALLFOLDER" On="uninstall"/>
            <RemoveFolder Id="INSTALLFOLDER" On="uninstall"/>
            <RegistryValue Root="HKLM" Key="$(var.RegDir)" Name="$(var.RegValueName)" 
                    Type="string" Value="[INSTALLFOLDER]" KeyPath="yes"/>
        </Component>
    </DirectoryRef>
</Fragment>

Và, trong phần tử Sản phẩm:

<Feature Id="Uninstall">
    <ComponentRef Id="UninstallFolder" Primary="yes"/>
</Feature>

Cách tiếp cận này đặt giá trị đăng ký với đường dẫn mong muốn của thư mục sẽ bị xóa khi gỡ cài đặt. Cuối cùng, cả INSTALLFOLDER và thư mục đăng ký đều bị xóa khỏi hệ thống. Lưu ý rằng đường dẫn đến sổ đăng ký có thể ở tổ ong khác và các vị trí khác.


6

Không phải là chuyên gia về WIX, nhưng có thể giải pháp khả thi (đơn giản hơn không?) Cho việc này là chạy Hành động tùy chỉnh thực thi yên lặng , một phần của các tiện ích mở rộng được tích hợp sẵn của WIX?

Có thể chạy lệnh rmdir MS DOS với các tùy chọn / S và / Q.

<Binary Id="CommandPrompt" SourceFile="C:\Windows\System32\cmd.exe" />

Và hành động tùy chỉnh thực hiện công việc rất đơn giản:

<CustomAction Id="DeleteFolder" BinaryKey="CommandPrompt" 
              ExeCommand='/c rmdir /S /Q "[CommonAppDataFolder]MyAppFolder\PurgeAppFolder"' 
              Execute="immediate" Return="check" />

Sau đó, bạn sẽ phải sửa đổi InstallExecuteSequence như được ghi lại ở nhiều nơi.

Cập nhật: Có vấn đề với cách tiếp cận này. Thay vào đó, đã kết thúc thực hiện một nhiệm vụ tùy chỉnh, nhưng vẫn coi đây là một giải pháp khả thi, nhưng không làm cho các chi tiết hoạt động.


Tôi thích thanh tùy chọn này vì bạn đang bao gồm cmd.exe trong trình cài đặt. Chắc chắn máy nào cũng có, bạn chỉ cần dùng DirectorySearch là có thể tìm được! :)
caveman_dick

4
Đừng làm điều này. 1) bạn đang nhúng cmd.exevào trình cài đặt của mình. 2) Bạn đang làm thay đổi hệ thống trong kịch bản thế hệ 3) Không có tùy chọn rollback 4) Không đối phó với các tập tin bị khóa một cách chính xác
Nick Whaley

Tôi nghi ngờ rằng việc phân phối tệp từ cài đặt Windows là hợp pháp. Cũng không rõ liệu nó có hoạt động trên hệ thống đích có thể chạy một phiên bản Windows khác hay không.
Paul B.

Không có tệp nào được phân phối. Nó sử dụng các tệp được cài đặt trên hệ điều hành.
tronda
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.