WiX 제거시 파일 제거


84

내 애플리케이션을 제거 할 때 원래 설치 후 추가 모든 파일을 제거 하도록 Wix 설정을 구성하고 싶습니다 . 제거 프로그램은 MSI 파일에서 원래 설치된 디렉토리와 파일 만 제거하고 나중에 추가 된 모든 파일은 응용 프로그램 폴더에 남겨 둡니다. 즉, 제거 할 때 디렉토리를 제거하고 싶습니다. 어떻게하나요?

답변:


83

On = " uninstall " 과 함께 RemoveFile 요소 를 사용하십시오 . 예를 들면 다음과 같습니다.

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

최신 정보

100 % 작동하지 않았습니다. 파일을 제거했지만 추가 디렉토리 (설치 후 생성 된 디렉토리)는 제거되지 않았습니다. 그것에 대한 생각은? – 프리 베이로

불행히도 Windows Installer는 하위 디렉터리가있는 디렉터리 삭제를 지원하지 않습니다. 이 경우 사용자 지정 작업에 의존해야합니다. 또는 하위 폴더가 무엇인지 알고있는 경우 RemoveFolder 및 RemoveFile 요소를 만듭니다.


1
파벨 감사합니다. 그러나 그것은 100 % 작동하지 않았습니다. 파일을 제거했지만 추가 디렉토리 (설치 후 생성 된 디렉토리)는 제거되지 않았습니다. 그것에 대해 어떤 생각?
pribeiro

아, 그 디렉토리 아래의 파일은 삭제되지 않았습니다.
pribeiro

메이저 업그레이드에서 파일 (예 : 구성 파일)을 'MyAppFolder'에 보관하면이 접근 방식에 문제가 발생합니다. 모든 파일은 업그레이드로 제거됩니다.
Simon

1
MyAppFolder에 디렉토리를 생성하는 코드가 있습니까? 후에 내가 디렉토리를 추가 할 때 </Component>내가 가진 컴파일 실패Found orphaned Component 'MyAppFolder'.
A.Pissicat


30

RemoveFolderExWiX에서 Util 확장의 요소를 사용합니다 .
이 접근 방식을 사용하면 모든 하위 디렉터리도 제거됩니다 ( element를 직접 사용RemoveFile 하는 것과 반대 ). 이 요소는 MSI 데이터베이스의 RemoveFileRemoveFolder테이블에 임시 행을 추가 합니다.


2
경고 : RemoveFolderEx on = "uninstall"을 사용하면 업그레이드시 폴더도 제거됩니다 (Wix 3.9). RemoveFile및에서 동일한 동작 RemoveFolder. 업그레이드시 파일을 유지하려는 경우 이러한 접근 방식을 모두 사용할 수는 없습니다.
사이먼

@Simon 업그레이드에 파일을 유지하려면 어떤 접근 방식을 제안 하시겠습니까?
Bijington

@Bijington : 업그레이드시 특정 파일을 설치 폴더에 보관하려면 사용자 지정 코드를 실행하는 사용자 지정 작업을 사용하십시오 (예 : C # 작성된 HandleSetup.exe). 사용자 정의 코드는 설치시 파일을 제공하여 업그레이드시 파일을 유지하고 제거시 파일을 제거합니다.
사이먼

@Simon 감사합니다. 이것이 현재 작동하고 있지만 그 접근 방식을 조사해야 할 수도 있습니다 : stackoverflow.com/a/21383113/32348
Bijington

13

이를 위해 간단히 제거 할 때 호출 할 사용자 지정 작업을 만들었습니다.

WiX 코드는 다음과 같습니다.

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

InstallerCustomActions.DLL의 OnBeforeUninstall 메서드에 대한 코드는 다음과 같습니다 (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

@tronda의 제안에 대한 변형이 있습니다. 제거 중에 다른 사용자 지정 작업에 의해 생성 된 "install.log"파일을 삭제합니다.

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

내가 아는 한 "RemoveFile"을 사용할 수 없습니다.이 파일은 설치 후 생성되고 구성 요소 그룹의 일부가 아니기 때문입니다.


4
이 솔루션을 사용하여 전체 디렉토리를 제거했습니다. ExeCommand = "cmd / C RD & quot; [INSTALLFOLDER] & quot; / s / q"
Dennis

@Dennis INSTALLFOLDER 삭제 방법, win 10에서는 삭제되지만 Windows Server 2012에서는 삭제되지 않습니다.
eomeroff

훌륭한 솔루션입니다. 감사!
Yurii Komarnytskyi

나는 많은 것을 시도했다-하나는 제거하는 동안 단일 파일을 제거하는 것이 그렇게 어려울 수 있다고 생각하지 않을 것이다. 이것은 나를 위해 일했습니다-감사합니다!
Lucky Luke

7

이것은 @Pavel 제안에 대한 더 완전한 대답이 될 것 입니다. 저에게는 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>

그리고 제품 요소에서 :

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

이 접근 방식은 제거시 삭제할 폴더의 원하는 경로로 레지스트리 값을 설정합니다. 마지막으로 INSTALLFOLDER와 레지스트리 폴더가 모두 시스템에서 제거됩니다. 레지스트리 경로는 다른 하이브 및 기타 위치에있을 수 있습니다.


6

WIX 전문가는 아니지만 WIX 의 기본 제공 확장의 일부인 Quiet Execution Custom Action실행 하는 것이 가능한 (더 간단한?) 해결책이 될 수 있습니까?

/ S 및 / Q 옵션을 사용 하여 rmdir MS DOS 명령을 실행할 수 있습니다.

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

작업을 수행하는 사용자 지정 작업은 간단합니다.

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

그런 다음 여러 곳에서 문서화 된대로 InstallExecuteSequence를 수정해야합니다.

업데이트 : 이 접근 방식에 문제가있었습니다. 대신 사용자 지정 작업을 작성했지만 여전히 이것이 실행 가능한 솔루션이라고 생각하지만 세부 사항이 작동하지 않습니다.


이 옵션 막대는 설치 프로그램에 cmd.exe를 포함하고 있다는 사실을 좋아합니다. 확실히 모든 기계가 그것을 가지고있을 것입니다. 당신은 그것을 찾기 위해 DirectorySearch를 사용하기 만하면됩니다! :)
caveman_dick

4
이러지마 1) cmd.exe설치 프로그램에 포함 하고 있습니다. 2) 당신은 스크립트 생성 3) 잠긴 파일을 처리하지 않습니다 더 롤백 옵션 4) 제대로 없다 동안 시스템을 변경하고 있습니다
닉 Whaley

Windows 설치에서 파일을 배포하는 것이 합법적인지 의심합니다. 다른 버전의 Windows를 실행할 수있는 대상 시스템에서 작동하는지 여부도 불분명합니다.
Paul B.

배포 된 파일이 없습니다. OS에 설치된 파일을 사용합니다.
tronda
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.