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'
Related
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
i have created a custom action for getting sites from IIS server.when i run it in my local machine it's working perfectly.but when i run it in another machine it's not working.
locator for custom action
<"Binary Id ="IisManager" SourceFile="$(var.SourceDir)\bin\CustomActions.CA.dll"/>
("used for foarmat this)
<UI Id="MyWixUI_Mondo">
<UIRef Id="WixUI_Mondo"/>
<UIRef Id="WixUI_ErrorProgressText" />
<DialogRef Id="IisSettings" />
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="IisSettings" Order="3">LicenseAccepted = "1"</Publish>
<Publish Dialog="SetupTypeDlg" Control="Back" Event="NewDialog" Value="IisSettings">1</Publish>
<InstallUISequence>
<Custom Action="GetIISWebSites" After="CostFinalize" Overridable="yes">NOT Installed</Custom>
<Custom Action="GetIISAppPools" After="CostFinalize" Overridable="yes">NOT Installed</Custom>
</InstallUISequence>
</UI>
have i done something wrong? working only in my machine...
Your custom action is crashing because it's referencing a COM class that is not registered on the other machine. Apparently that CLSID belongs to Microsoft.ApplicationHost.WritableAdminManager and the ServerManager managed API, so if they are not present on the target machine your code will fail. A web search for -CLSID {2B72133B-3F5B-4602-8952-803546CE3344- may get you some more info, but this isn't a WiX or Windows Installer issue as far as I can tell.
Running Setup file with Administrative privileges resolved the issue.
CMD ->>Run As administrator -> Go To setup file and Run it.
I have a MSI installer and I specify per-machine installation in the installer UI. Previous version was also installed per-machine.
However, FindRelatedProducts reports that current install is per-user.
MSI (c) (A4:F0) [13:33:20:490]: FindRelatedProducts: **current install is per-user**. Related install for product '<<my guid>>' is per-machine. Skipping...
From the log I can see that ALLUSERS property is created only after FindRelatedProducts ran (note timestamp):
MSI (c) (A4:A8) [13:33:25:032]: PROPERTY CHANGE: Adding ALLUSERS property. Its value is '2'.
The property ALLUSERS is Published from the UI based on what the user selected:
<Publish Property="ALLUSERS" Value="2"><![CDATA[FolderForm_AllUsers="ALL" AND VersionNT>=400 AND Privileged=1 AND FolderForm_AllUsersVisible=1]]></Publish>
<Publish Property="ALLUSERS" Value="{}"><![CDATA[FolderForm_AllUsers="ME" AND VersionNT>=400 AND Privileged=1 AND FolderForm_AllUsersVisible=1]]></Publish>
<Control Id="AllUsersRadioGroup" Type="RadioButtonGroup" X="20" Y="175" Width="342" Height="42" Property="FolderForm_AllUsers" Text ="empty">
<RadioButtonGroup Property="FolderForm_AllUsers">
<RadioButton Value="ALL" X="0" Y="0" Width="342" Height="17" Text="$(loc.InstallForAll)" />
<RadioButton Value="ME" X="0" Y="18" Width="342" Height="17" Text="$(loc.InstallForMe)" />
</RadioButtonGroup>
<Condition Action="show"><![CDATA[VersionNT>=400 AND Privileged=1 AND FolderForm_AllUsersVisible=1]]></Condition>
<Condition Action="hide"><![CDATA[NOT (VersionNT>=400 AND Privileged=1 AND FolderForm_AllUsersVisible=1)]]></Condition>
</Control>
As a result, the new version is installed alongside the existing (two entries exist in Add/Remove programs).
<InstallUISequence>
<Custom Action="VSDCA_FolderForm_AllUsers" After="IsolateComponents"><![CDATA[Installed="" AND NOT RESUME AND ALLUSERS=1]]></Custom>
<Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>
</InstallUISequence>
<InstallExecuteSequence>
<!-- Only schedule this custom action for the 32-bit MSI. -->
<?if $(var.DependenciesPlatform)=x86 ?>
<Custom Action="CA_Err32BitMsiOn64BitOS" After="LaunchConditions">
<![CDATA[MsiAMD64 OR Intel64]]>
</Custom>
<?endif ?>
<!-- Prevent downgrading -->
<Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>
<RemoveExistingProducts Before="InstallInitialize" />
<Custom Action="LaunchApp" After="InstallFinalize" />
<InstallInitialize></InstallInitialize>
<RemoveShortcuts></RemoveShortcuts>
<InstallFiles></InstallFiles>
<CreateShortcuts></CreateShortcuts>
<InstallFinalize></InstallFinalize>
<ScheduleReboot After="InstallFinalize"/>
</InstallExecuteSequence>
This occurs only in case both versions of the app are installed per-machine, since FindRelatedProducts apparently assumes per-user installation (because it runs before the user was able to pick one of the radio buttons and therefore there is no ALLUSERS propety set at the time it runs).
How do I ensure that FindRelatedProducts is executed only after ALLUSERS was Published from the UI as specified by the user?
I found I need to add the following to ensure FindRelatedProducts runs within the UI after the user made his choice:
<Publish Event="DoAction" Value="FindRelatedProducts">1</Publish>
From https://www.mail-archive.com/wix-users#lists.sourceforge.net/msg22960.html
I found it is not strictly needed to use the suppress attribute - it seems to work also without explicitly suppressing the action in the InstallUISequence.
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.
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. :)