How do I execute file installed by merge module? - wix

I am using WIX and have successfully used a custom action to execute installed file at the end of installer like this:
<CustomAction Id="LaunchAfterInstall" FileKey="foobar.exe" ExeCommand="parameters" Execute="immediate" Impersonate="yes" Return="asyncNoWait" />
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION"/>
<UIRef Id="WixUI_InstallDir" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Launch Foobar." />
<UI>
<Publish Dialog="ExitDialog" Control="Finish" Order="1" Event="DoAction" Value="LaunchAfterInstall">WIXUI_EXITDIALOGOPTIONALCHECKBOX</Publish>
</UI>
This works well when foobar.exe is in a component in the same wxs file. However what I really want is to execute a file that is installed by a merge module. How do I do this?
I can make changes in the merge module, if this helps things.

I changed the action to solve my problem:
<CustomAction Id="LaunchAfterInstall" Directory="INSTALLLOCATION" ExeCommand="[INSTALLLOCATION]\foobar.exe" Execute="immediate" Impersonate="yes" Return="asyncNoWait" />

You can also open the Merge Module in Orca or your MSI after the build is complete (i.e. the Merge Module has been merged in) and look up the File.Id. Then use the File.Id in the CustomAction.
Ideally though the MSI shouldn't refer to content inside the Merge Module since Merge Modules are supposed to be independent. I appreciate it doesn't always work out that way. :)

Related

Prevent downgrading from a bundle

before I would just use 1 wxs project file to install my app. This would uninstall all previous versions before installing.
Now I have added a bundle and it no longer works. If I change the setup file like adding another file or registry setting and attempt install it will create another entry in my program and features list.
How can i get the same action/behavior from a bundle?
This snippet is what is inside my Product wxs file:
<MajorUpgrade
AllowDowngrades="no"
AllowSameVersionUpgrades="no"
IgnoreRemoveFailure="no"
DowngradeErrorMessage="loc.NewerVersionInstalled"
Schedule="afterInstallInitialize"/>
<InstallUISequence>
<Custom Action='PreventDowngrading' After='FindRelatedProducts'>NEWPRODUCTFOUND</Custom>
</InstallUISequence>
<CustomAction Id='PreventDowngrading' Error='Newer version already installed' />
<Property Id="WIXUI_INSTALLDIR" Value="APPLICATIONROOTDIRECTORY" />
<UI>
<UIRef Id="WixUI_Minimal" />
<Publish
Dialog="ExitDialog"
Control="Finish"
Event="DoAction"
Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed
</Publish>
</UI>
thanks

Enable logging in wix installer

How can I enable logging in my wix project and set MsiLogFileLocation?
Now I am running my install.msi with command line arguments:
msiexec /i install.msi /l*v InstallLog.log
I want to log my work always just running install.msi without any arguments. Are there any way to do that?
You can tell WiX to use verbose logging like this:
<Property Id="MsiLogging" Value="v" />
but you can't specify where to write the file - msiexec has already determined that by the time WiX gets to set the property. It'll default to %TEMP%\MSI{random chars}.LOG. You could offer the user a checkbox to determine if they want to open that log, like this (assuming you're using the built in InstallDir UI template - it'd be possible with others as well, but this is a pretty simple example):
<Property Id="MsiLogging" Value="v" />
<UI>
<UIRef Id="WixUI_InstallDir" />
<Publish Dialog="ExitDialog"
Control="Finish"
Event="DoAction"
Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
</UI>
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="View Installation Log" />
<WixVariable Id="WixUILicenseRtf" Value="license.rtf"/>
<Property Id="WixShellExecTarget" Value="[MsiLogFileLocation]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
This would copy the log file to a directory about as late as possible in the game, but would miss at least some of the tail end of the log:
<Property Id="MsiLogging" Value="v!" />
<CustomAction Id="CopyLog" Execute="immediate"
ExeCommand="cmd /c copy [MsiLogFileLocation] C:\temp\log.txt"
Directory="TARGETDIR"
Impersonate="no"
Return="asyncNoWait" />
<InstallExecuteSequence>
<Custom Action="CopyLog" OnExit="success" />
</InstallExecuteSequence>
Note that this won't work for the C: drive root, because that requires administrative privileges. If you're ok missing even more of the log, you could change OnExit='success' to After='InstallFinalize' and change the Execute attribute on the CustomAction to commit. That should allow it run as administrator.
See this discussion for a bit more: http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/Setting-MsiLogFileLocation-property-td7374335.html

WiX custom action by platform

I need to create a checkbox to install drivers after installation of program (just like run program checkbox). Additional problem is that driver depends on platform of system. I'm trying to do it like that:
<CustomAction Id="RunProgram" Directory="INSTALLFOLDER" ExeCommand="[INSTALLFOLDER]Application.exe" Return="asyncNoWait"/>
<CustomAction Id="RunDriver64" Directory="INSTALLFOLDER" ExeCommand="[INSTALLFOLDER]driver/Installer_x64.exe" Return="asyncNoWait"/>
<CustomAction Id="RunDriver32" Directory="INSTALLFOLDER" ExeCommand="[INSTALLFOLDER]driver/Installer_x86.exe" Return="asyncNoWait"/>
<InstallExecuteSequence>
<Custom Action="RunDriver64" After="InstallFinalize">'$(var.Platform)' != 'x64'</Custom>
<Custom Action="RunDriver32" After="InstallFinalize">'$(var.Platform)' == 'x64'</Custom>
</InstallExecuteSequence>
<UI>
<Publish Dialog="ExitDialog" Control="Finish" Order="2" Event="DoAction" Value="RunProgram">
WIXUI_EXITDIALOGOPTIONALCHECKBOX
</Publish>
</UI>`
but it doesn't work. Error message:
Error 1 ICE03: Bad conditional string; Table: InstallExecuteSequence, Column: Condition, Key(s): RunDriver64 F:..path..\Product.wxs 26 1 ..project name..
Also my solution is not perfect, as I'm running there a action I don't realy want 'RunProgram', but I couldn't create empty action. Any suggestions, how can I do that?
Thanks
You'll need to wrap it in CDATA
Try <![CDATA[NOT(VersionNT64)]]> and <![CDATA[(VersionNT64)]]> instead of '$(var.Platform)' != 'x64' and '$(var.Platform)' == 'x64'

WIX. Set environment variable and run application after installation

I developed a custom installer with WIX for a .NET application.
In this installer I set environment variable
<Environment Id="COMPLUS_Version" Action="set" Part="all" Name="COMPLUS_Version"
Permanent="yes" System="yes" Value="v4.0.30319" />
and after installation I run application (this environment variable need to be set for correct running apllication).
<UI Id="MyWixUI_Mondo">
<UIRef Id="WixUI_Advanced" />
<Publish Dialog="ExitDialog"
Control="Finish"
Event="DoAction"
Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
</UI>
<Property Id="WixShellExecTarget" Value="[#Application]" />
<CustomAction Id="LaunchApplication"
BinaryKey="WixCA"
DllEntry="WixShellExec"
Impersonate="yes" />
But, sometimes it doesn't work. For example, in Windows 7 Enterprise x86 apllication run after installation with errors (only after installation).
UPD. This problem appear when UAC is disabled.

Executing a custom action that requires elevation after install

I have the following WiX snippet:
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
<CustomAction Id="StartAppOnExit"
FileKey="Configurator.exe"
ExeCommand=""
Execute="immediate"
Impersonate="yes"
Return="asyncNoWait" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT"
Value="Configure initial settings" />
<UI>
<Publish Dialog="ExitDialog"
Control="Finish"
Order="1"
Event="DoAction"
Value="StartAppOnExit"
>WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
</UI>
Basically on the exit dialog I display a box that says: launch application. Note: this application requires elevation. This all works fine except for a snag. If UAC is enabled it seems that the MSI mucks around with the user token and strips its groups, so when it tries to launch the application that requires elevation it is no longer an option.
How do I string this together to work?
I tried chucking an Impersonate="no", but it's too late at that point for this to work.
The UI sequence is running as a limited user, and it launches applications with a call to CreateProcess. If you use something like a WixShellExec with [WixShellExecTarget] instead, it will act like Explorer and show a UAC prompt if the target requires elevation. Or you could modify your Configurator.exe to allow being launched without elevated privileges, detect that case, and relaunch itself with elevated privileges.
For example, this should work:
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
<CustomAction Id="StartAppOnExit" BinaryKey="WixCA" DllEntry="WixShellExec" Execute="immediate" Return="check" Impersonate="yes"/>
<Property Id="WixShellExecTarget" Value="[#Configurator.exe]"/>
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Configure initial settings" />
<UI>
<Publish Dialog="ExitDialog" Control="Finish" Order="1" Event="DoAction" Value="StartAppOnExit">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
</UI>
FYI, Immediate custom actions are ALWAYS impersonated (i.e. they always run as the user who executes the MSI).
I like Michael Urman's idea regarding making your Configurator.exe handle the elevation issue.
I wonder if you could also just include a manifest in your EXE so that the OS knows elevation is always required.