卸载应用程序时如何删除安装文件夹?安装文件夹碰巧被msiexec.exe进程锁定

时间:2016-07-27 23:42:47

标签: windows wix windows-installer

我花了一天时间试图做最简单的事情。 (男人,MSI / WiX很少!)

我的目标非常简单。卸载我的应用程序时,我需要删除安装文件夹。我这样创建它(使用WiX):

<Directory Id='TARGETDIR' Name='SourceDir'>
  <Directory Id='ProgramFilesFolder' Name='InstallFolder'>
    <Directory Id='idCompany.com' Name='$(var.CompanyName)'>
      <Directory Id='INSTALLDIR' Name='$(var.ProductThis)' >

        <Component Id='CompIDMyEXE1' Guid='{--GUID1--}'>
          <File Id='idMyEXE1' Name='MyExe1.exe' DiskId='1' Source='MyExe1.exe' Vital='yes' KeyPath='yes' />
          <ServiceControl Id="idSrvc" Name="SrvcName" Stop="both" Wait="yes" />
        </Component>

        <Component Id='CompIDMyEXE2' Guid='{--GUID2--}'>
          <File Id='idMyEXE2' Name='MyExe2.exe' DiskId='1' Source='MyExe2.exe' Vital='yes' KeyPath='yes' />
        </Component>

    <!-- and so on -->

      </Directory>
    </Directory>
  </Directory>

我首先尝试使用RemoveFolder WiX关键字,因为它是suggested here,但无论我做了什么,我的安装文件夹都不想去。更糟糕的是,没有办法知道它为什么不起作用。没有看到我的标签,或者是什么...... arghhh!

所以我决定添加一个用C编写的自定义动作并从那里删除该文件夹,因为我会有更多的控制权。所以我这样做了:

<CustomAction Id="CA_SetProperties_UninstallFinalize" Property="CA_msiOnUninstallFinalize" Value="[INSTALLDIR]" />
<CustomAction Id='CA_msiOnUninstallFinalize' BinaryKey='CADll' DllEntry='msiOnUninstallFinalize' Execute='deferred' Impersonate='no' />

<InstallExecuteSequence>

  <!-- Need to run it for uninstalls only -->
  <Custom Action="CA_SetProperties_UninstallFinalize" Before="InstallFinalize">
    NOT REINSTALL AND NOT UPGRADINGPRODUCTCODE AND REMOVE
  </Custom>
  <Custom Action="CA_msiOnUninstallFinalize" After="CA_SetProperties_UninstallFinalize">
    NOT REINSTALL AND NOT UPGRADINGPRODUCTCODE AND REMOVE
  </Custom>

  <!-- ... -->

</InstallExecuteSequence>

但是当我在空的安装文件夹中使用msiOnUninstallFinalize方法调用RemoveDirectory API时,它会一直返回ERROR_SHARING_VIOLATION错误。

所以我在msiOnUninstallFinalize方法中放了一个休息点(只需添加一个MessageBox调用)并检查文件夹本身。事实证明,那个时候的文件夹已经是空的,但是当我检查它是否锁定它时,事实证明MSI本身正在持有它:

enter image description here

那么这里有什么问题?怎么做这个简单的任务????

1 个答案:

答案 0 :(得分:1)

真是奇怪的问题。事实证明,我创建了一个&#34;卸载&#34;我用来卸载应用程序的快捷方式:

<Shortcut Id="startmenuUninst"
    Directory="ProgramMenuDir"
    Target="[SystemFolder]msiexec.exe"
    Arguments="/x [ProductCode]"
    Name="Uninstall $(var.ProductThis)"
    WorkingDirectory='INSTALLDIR'
    Advertise='no'
    Description="Uninstalls $(var.ProductThis)" />

调用WorkingDirectory进程时,问题恰好是msiexec属性或Windows工作目录。出于某种原因,如果将其设置为要删除的文件夹(例如,在这种情况下为INSTALLDIRmsiexec进程将对其进行内部锁定,因此在此期间不会删除该文件夹卸载。

在我的案例中解决方案非常简单。我需要将INSTALLDIR替换为任何其他文件夹,例如:WorkingDirectory='SystemFolder'并自动将其删除,而不需要任何自定义操作,就像我上面显示的那样。

PS。顺便说一句,如果您使用msiexec.exe /x {Product-Code-GUID}命令从C / C ++调用CreateProcess来卸载应用程序,请确保指定一个工作目录,该目录不是要删除的文件夹。 lpCurrentDirectory参数。不要使用NULL因为它可能会导致当前工作目录的歧义,如上所述。