2
votes

I have a custom action "xxxx" which deletes directory by executing rmdir through command prompt. ExeCommand="[SystemFolder]cmd.exe /C rmdir /Q /S "[DIR]"" and Execute="deferred"

It is added in InstallExecuteSequence as below

Custom Action="xxxx" After="InstallInitialize"
  (NOT UPGRADINGPRODUCTCODE) AND REMOVE
Custom

If the directory is opened by some other application such as command line, then it throws error.

I read many similar issues. But couldn't figure out on

1) prompt user to close applications - I read adding

UI
  DialogRef Id="FilesInUse" 
  DialogRef Id="MsiRMFilesInUse" 
/UI

and using custom action Before="InstallValidate" shows prompt to close applications.

2) How to run custom action after services are stopped and prompt user to close applications? It should run in deferred mode.

3) If I want to run in Execute = deferred, then I can't use InstallValidate. Therefore I can't use FilesInUse.

4) Is there any other good approach? I don't want to reference a dll because I want the installer to delete entire directory on uninstall.

1

1 Answers

2
votes

The big question is why you need to remove that folder because normally you don't need to. That means it must be getting left behind, but that's just a guess, so I'd say that's the problem to deal with - why it's left behind. Your question is about why your solution isn't working. The underlying issue is that InstallValidate will prompt a FilesInUse dialog if Windows decides it needs one, and Windows doesn't need one - you do because of your custom action - that's why FilesInUse UI refs aren't helping.

If you want to remove files or folders, the WiX RemoveFile element is the usual way, and it happens at the right point in the uninstall where everything else has beeen removed:

Wix RemoveFile and RemoveFolder for removing leftovers

If you want to tell an app to shut down, there is the WiX Util CloseApplication.

If you really want to solve the folder issue with your code and a FilesInUse prompt (rather then address the underlying issue of that folder) then a C++ custom action like this will show a FilesInUse dialog, immediate before InstallValidate should work, you'll need some includes of msi.h, msiquery.h:

UINT __stdcall ShowFilesInUse (MSIHANDLE hInstall) 
{
PMSIHANDLE hRec = MsiCreateRecord(4);
MsiRecordSetString(hRec, 1, TEXT(" "));
MsiRecordSetString(hRec, 2, TEXT("Please use Task Manager to Terminate these programs:"));
MsiRecordSetString(hRec, 3, TEXT("something else"));
UINT res = 0;
do 
{
res = MsiProcessMessage(hInstall, INSTALLMESSAGE_FILESINUSE, hRec);
}
while (res == IDRETRY);
if (IDOK==res) // 1 is the Continue button in VS
   return 0; 
if (IDCANCEL ==res) // The Exit button in VS 
   return ERROR_INSTALL_USEREXIT;
return 0;
}