2016-07-27 4 views
0

私は文字通り、最も簡単なことをしようとしました。 (男、MSI/WiXは一握りです!)アプリをアンインストールしたらインストールフォルダを削除するには?インストールフォルダは、msiexec.exeプロセスによってロックされます。

私の目標はとても簡単です。私は、アプリケーションがアンインストールされたときにインストールフォルダを削除する必要があります。私は(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> 

私が最初にそれがsuggested hereあったようRemoveFolder WiXのキーワードを使用しようとしましたが、私は私のインストールフォルダやったことに関係なく行きたくありませんでした。問題を悪化させたのは、なぜそれがうまくいかなかったのかを知る方法がないことです。単に私のタグを見ていない、または何... 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> 

が、私はそれは ERROR_SHARING_VIOLATIONエラーを返すまま私の空のインストールフォルダに私の msiOnUninstallFinalize方法から RemoveDirectory APIを呼び出したときに:だから私はこれをしませんでした。

私は自分のmsiOnUninstallFinalizeメソッド内に休憩を入れて(MessageBoxコールを追加するだけで)、フォルダ自体をチェックしました。それは、判明している時点でのフォルダがすでに空でしたが、私はそれにロックがありますかどうかを確認するためにチェックすると、それは、MSI自体がそれを保持していることが判明:

enter image description here

ので、ここでこするは何でしょう?どのようにこの単純な仕事を行うために一体?

+0

あなたは 'InstallFinalize'の後でカスタムアクションを呼び出そうとしましたか?それが私のやり方であり、削除することができない(または削除したくない)すべてのフォルダが削除されます。 –

+0

@MikeDelta: 'InstallFinalize'の後に' Execute = 'deferred''属性で呼び出すことはできません。保護されたOSの場所、つまり '' C:\ Program Files \ "\ – c00000fd

答えて

1

本当に奇妙な問題です。それは私のような、アプリをアンインストールするために使用していたことを、私は「アンインストール」のショートカットを作成したことが判明:

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

問題がmsiexecプロセスが呼び出されたときWorkingDirectory属性、またはWindows作業ディレクトリであることを起こります。なんらかの理由で、削除されるフォルダ(この場合はINSTALLDIRのような)に設定されている場合、msiexecプロセスに内部ロックが設定され、アンインストール時にフォルダが削除されません。

したがって私の場合の解決はかなり簡単でした。 INSTALLDIRWorkingDirectory='SystemFolder'などの他のフォルダに置き換える必要がありました。上に示したように、カスタムアクションを必要とせずに自動的に削除されました。

PS。ちなみに、msiexec.exe /x {Product-Code-GUID}コマンドでC/C++からCreateProcessを呼び出してアプリをアンインストールする場合は、削除するフォルダ以外の作業ディレクトリをlpCurrentDirectoryパラメータで指定してください。 NULLを使用しないでください。これは、上で説明したように、現在の作業ディレクトリであいまいさを引き起こす可能性があります。

+0

からフォルダを削除する必要があるかもしれません。あなたの答えを受け入れる方が良いかもしれません。この質問はまだ開いていません。 – Wolf

関連する問題