2
votes

I am trying to run a console application written in C# .NET 2.0 in a custom action in my WiX MSI setup project like this:

<CustomAction Id="INSTALL_TEXT" Impersonate="yes" Return="check" Execute="immediate" BinaryKey="TextCreator.exe" ExeCommand="C:\test.txt -i"/>
<CustomAction Id="UNINSTALL_TEXT" Impersonate="yes" Return="check" Execute="immediate" BinaryKey="TextCreator.exe" ExeCommand="C:\test.txt -u"/>
<Binary Id="TextCreator.exe" SourceFile="C:\MyInstaller\Test\Tools\TextCreator.exe"/>
<InstallExecuteSequence>
  <Custom Action="INSTALL_TEXT" After="InstallFiles">NOT Installed AND NOT PATCH</Custom>
  <Custom Action="UNINSTALL_TEXT" After="RemoveFiles">Installed AND REMOVE="ALL"</Custom>
</InstallExecuteSequence>

But I am always getting an error message in the log:

MSI (s) (7C:C0) [14:03:01:026]: Note: 1: 1721 2: INSTALL_TEXT 3: C:\Windows\Installer\MSI9938.tmp 4: C:\test.txt -i
Error 1721. There is a problem with this Windows Installer package. A program required for this install to complete could not be run. Contact your support personnel or package vendor. Action: INSTALL_TEXT, location: C:\Windows\Installer\MSI9938.tmp, command: C:\test.txt -i
MSI (s) (7C:C0) [14:03:07:374]: Product: Text Creator Console App -- Error 1721. There is a problem with this Windows Installer package. A program required for this install to complete could not be run. Contact your support personnel or package vendor. Action: INSTALL_TEXT, location: C:\Windows\Installer\MSI9938.tmp, command: C:\test.txt -i
Action ended 14:03:07: INSTALL_TEXT. Return value 3.

I have embedded a MANIFEST in my application to run with administrative privileges:

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

When I run the installer from command line where the console prompt has already been started with administrative privileges, both install and uninstall work fine! But when I start the MSI using double-click I am asked to run the installation (before progress bar continues) if I want to run with administrative privileges. Then my setup aborts with the error message as provided in the LOG above.

What leads to that problem? I am using WiX 3.5.2519.0 with MSI 2.0 in my project. My setup is running on Windows 7 Professional (x64). I have all frameworks installed from 2.0, through 3.0, 3.5 up to 4.0!

EDIT: On Windows XP with .NET Framework 2.0 installed, all works just fine!

SOLUTION:

<CustomAction Id="QtExecInstallText" Impersonate="no" Return="check" Execute="deferred" BinaryKey="TextCreator.exe" ExeCommand="C:\test.txt -i"/>
<CustomAction Id="QtExecUninstallText" Impersonate="no" Return="check" Execute="deferred" BinaryKey="TextCreator.exe" ExeCommand="C:\test.txt -u"/>
<Binary Id="TextCreator.exe" SourceFile="C:\MyInstaller\Test\Tools\TextCreator.exe"/>
<InstallExecuteSequence>
  <Custom Action="QtExecInstallText" After="InstallFiles">NOT Installed AND NOT PATCH</Custom>
  <Custom Action="QtExecUninstallText" After="RemoveFiles">Installed AND REMOVE="ALL"</Custom>
</InstallExecuteSequence>

=> When linking pass -ext "%WIX%\bin\WixUtilExtension.dll" to light.exe!

1

1 Answers

2
votes

The cleanest way to run any EXE in an MSI installer is using Quiet Execution Custom Action.

Examples of how to implement it are on the linked page. FWIW, a properly scheduled custom action (deferred with no impersonation) will already be running as system and manifest / UAC elevation won't apply. Additionally, if you can refactor your .NET EXE to be a client/server (EXE / DLL) arrangement then you can take the server class and consume it in a Deployment Tools Foundation (DTF) custom action.

This is a much better design as it runs in process rather than out of process and can call MSI APIs such as getting CustomActionData attributes, writing to the MSI log, returning ErrorSuccess and/or publishing progress bar updates and action messages. Forking to an EXE file is a hack compared to this.