1
votes

We have distributed an old version of our wix installer with some files installed as Permanent="yes" components. But now we want to ask the user for retain or delete those files on unistall. This files are located on Program Files folder. We get on DELETE_ALL the user response. This is:

 <InstallExecuteSequence>
      <!-- more custom actions -->
      <Custom Action="DeleteFiles" Before="InstallFinalize">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL") AND (NOT (DELETE_ALL=0))</Custom>
 </InstallExecuteSequence>
<CustomAction Id="DeleteFiles" ExeCommand='Company.CustomActions.ExeActions.exe' Directory="INSTALLDIR" Return="check" Impersonate="yes" Execute="immediate" />

Company.CustomActions.ExeActions.exe is a simple console application than delete those files on C:\Program Files (x86)\Company\Program1 with a manifest with

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

On .msi execution we get this lines:

MSI (s) (20:88) [15:16:19:130]: MSI_LUA: Elevation required to install product, will prompt for credentials
MSI (s) (20:88) [15:16:21:798]: MSI_LUA: Credential Request return = 0x0
MSI (s) (20:88) [15:16:21:798]: MSI_LUA: Elevated credential consent provided. Install will run elevated

Or if we launch it from Administrator cmd.exe:

MSI (c) (24:F8) [12:35:32:530]: MSI_LUA: Setting AdminUser property to 1 because this is the client or the user has already permitted elevation

We try to set for our DeleteFiles custom action set diferent values for Impersonate (yes/no) and Execute (immediate/deferred) without get success on it.

Further we try to do this deletion by a component with RemoveFiles or on a CustomAction written in c# marked with a CustomActionAttribute like others we use. Also no success.

    [CustomAction]
    public static ActionResult DeleteAll(Session session) { /*...*/ }

Or calling from CustomAction to another method:

[PrincipalPermission(SecurityAction.Demand, Role = @"BUILTIN\Administrators")]
private static void DeleteFiles()  { /*...*/ }

We get an expcetion:

 Request for principal permission failed.
 at System.Security.Permissions.PrincipalPermission.ThrowSecurityException()
 at System.Security.Permissions.PrincipalPermission.Demand()
 at System.Security.PermissionSet.DemandNonCAS()
 at Company.CustomActions.DeleteFiles(Session session)
 at Company.CustomActions.DeleteALL(Session session)

It's possible to implement a feature to delete permanent files installed in previous version on demand? Any idea?

2

2 Answers

1
votes

You should set custom action to be executed as deferred with no impersonation

<CustomAction Id="DeleteFiles" ExeCommand='Company.CustomActions.ExeActions.exe' Directory="INSTALLDIR" Return="check" Impersonate="no" Execute="deferred" />
0
votes

Finally we use WixShellExec from binary WixCA that we have been used before (in time, not in execution) for launching a privileged application, setting the value of WixShellExecTarget just before schedule every WixShellExec cutom action.

The real problem is that that way doesn't allow retrieve real errors on custom actions (not the errors on WixShellExec call, but the underlying ones). By the moment is a valid scenario for us. So we solved it this way.

Example:

<InstallExecuteSequence>
   <!-- more custom actions -->
  <Custom Action="SetLaunchDeleteAll" Before="InstallFinalize">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL") AND (NOT (DELETE_ALL=0))</Custom>
  <Custom Action="DeleteFiles" Before="InstallFinalize">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL") AND (NOT (DELETE_ALL=0))</Custom>
</InstallExecuteSequence>
<InstallUISequence>
 <!-- more custom actions -->
  <Custom Action="SetLaunchProperty" Sequence="9990">CUSTOM_CONDITIONS</Custom>
</InstallUISequence>
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Execute="immediate" Impersonate="yes" Return="check" />
<!-- more custom actions -->
<CustomAction Id="DeleteFiles" BinaryKey="WixCA" DllEntry="WixShellExec" Execute="immediate" Impersonate="yes" Return="check" />
<CustomAction Id="SetLaunchProperty" Property="WixShellExecTarget" Value="[#Company.Program.exe]" />
<CustomAction Id="SetLaunchDeleteAll" Property="WixShellExecTarget" Value="[#Company.CustomActions.ExeActions.exe]" />
<UI>
  <Publish Dialog="MyExitDialog" Control="Finish" Order="1" Event="DoAction" Value="LaunchApplication">CUSTOM_CONDITIONS</Publish>
</UI>
<Property Id="WixShellExecTarget" Value="[#Company.CustomActions.ExeActions.exe]"/>

And DeleteAll() method isn't decorated with PrincipalPermissionAttribute, although the Company.CustomActions.ExeActions.exe manifest does require administrator permissions (requestedExecutionLevel requireAdministrator).

Uninstalling and asking for deletion shows twice UAC (once for uninstall and one more time for these custom action) with my local Windows configuration for these actions.