How to execute multiple launch conditions on installer exit - wix

I've managed to get WIX to launch my application on exit, but not sure how to schedule two custom actions using the WixShellExecTarget property.
One CA is to launch an app and the other is a web page based on a url from another CA. These are both launched if the appropriate checkboxes are checked.
<!-- Custom action for executing app -->
<Property Id="WixShellExecTarget" Value="[#Application.exe]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<!-- Custom action for executing Webbrowser -->
<Property Id="???" Value="[CONFIGWIZARDURL]" />
<CustomAction Id="LaunchConfigWizard" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
Any help you could give me to get this working would be greatly appreciated.
Cheers,
Jamie
[Edit] I've tried the suggestion below and I don't get it setting the appropriate value for the second action. It doesn't go to www.google.com as I suggest:
<Publish Dialog="MyExitDialog" Control="Finish" Event="DoAction" Value="SetExec1"><![CDATA[NOT Installed]]></Publish>
<Publish Dialog="MyExitDialog" Control="Finish" Event="DoAction" Value="DoExec"><![CDATA[LAUNCHCAPTURE = "1" AND NOT Installed]]></Publish>
<Publish Dialog="MyExitDialog" Control="Finish" Event="DoAction" Value="SetExec2"><![CDATA[NOT Installed]]></Publish>
<Publish Dialog="MyExitDialog" Control="Finish" Event="DoAction" Value="DoExec"><![CDATA[LAUNCHCONFIGWIZARD = "1" AND NOT Installed]]></Publish>
Property(S): LAUNCHCONFIGWIZARD = 1
MSI (s) (5C:DC) [14:41:02:119]: PROPERTY CHANGE: Adding CONFIGWIZARDURL property. Its value is 'http://www.google.com'.
MSI (c) (DC:60) [14:41:16:166]: PROPERTY CHANGE: Adding WixShellExecTarget property. Its value is 'C:\...Application\MyApplication.exe'.
Action ended 14:41:16: SetExec1. Return value 1.
MSI (c) (DC:60) [14:41:16:181]: Doing action: DoExec
Action 14:41:16: DoExec.
Action start 14:41:16: DoExec.
MSI (c) (DC:60) [14:41:16:181]: Creating MSIHANDLE (3) of type 790542 for thread 11104
MSI (c) (DC:E0) [14:41:16:181]: Invoking remote custom action. DLL: C:\Temp\MSIA7A.tmp, Entrypoint: WixShellExec
MSI (c) (DC!8C) [14:41:16:244]: Creating MSIHANDLE (4) of type 790541 for thread 10636
MSI (c) (DC!8C) [14:41:16:244]: Creating MSIHANDLE (5) of type 790531 for thread 10636
MSI (c) (DC!8C) [14:41:16:244]: Closing MSIHANDLE (5) of type 790531 for thread 10636
MSI (c) (DC!8C) [14:41:16:447]: Closing MSIHANDLE (4) of type 790541 for thread 10636
MSI (c) (DC:E0) [14:41:16:447]: Closing MSIHANDLE (3) of type 790542 for thread 11104
Action ended 14:41:16: DoExec. Return value 1.
MSI (c) (DC:60) [14:41:16:447]: Doing action: SetExec2
Action 14:41:16: SetExec2.
Action start 14:41:16: SetExec2.
MSI (c) (DC:60) [14:41:16:447]: PROPERTY CHANGE: Deleting WixShellExecTarget property. Its current value is 'C:\...Application\MyApplication.exe'.
Action ended 14:41:16: SetExec2. Return value 1.
Action ended 14:41:16: MyExitDialog. Return value 1.

Fairly straightforward, you'll need two separate actions to "set" WixShellExecTarget - they'll just run at different times.
First, you'll setup the actions that are going to be run.
<CustomAction Id="SetExec1" Property="WixShellExecTarget" Value="[#Application.exe]" />
<CustomAction Id="SetExec2" Property="WixShellExecTarget" Value="[CONFIGWIZARDURL]" />
<CustomAction Id="DoExec" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" Return="ignore" />
Now you want to schedule those actions to actually run, in this example I'm tying all of the actions to the Finish button on the final installation dialog. As we're publishing to a Control element, WiX will automatically set Publish/#Order to one greater than the previous event.
In addition, all these actions are conditioned to only execute during installation as this same dialog is displayed during removal and repair.
You'll likely also want to condition these based on the status of your checkboxes if execution is optional.
<UI>
<!-- Publish set/do for first action -->
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="SetExec1">
<![CDATA[NOT Installed]]>
</Publish>
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="DoExec">
<![CDATA[NOT Installed]]>
</Publish>
<!-- Publish set/do for second action -->
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="SetExec2">
<![CDATA[NOT Installed]]>
</Publish>
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="DoExec">
<![CDATA[NOT Installed]]>
</Publish>
</UI>

Related

wix customaction gives error 2896 when used with Publish Event="DoAction"

wxs file
<Dialog Id="InputParameters" Width="370" Height="270" Title="!(ll.MyDlg_Title)">
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)" >
<Publish Event="DoAction" Value="ValidateParameters" >1</Publish>
</Control>
<Dialogue>
<CustomAction Id="ValidateParameters" BinaryKey="my_dll.CA.dll" DllEntry="ValidateParametersFunc" Execute="immediate" />
CustomAction.cs file
[CustomAction]
public static ActionResult ValidateParametersFunc(Session session)
{
session.log("perform validation");
return ActionResult.Success;
}
CustomAction.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" />
<supportedRuntime version="v2.0.50727"/>
<configuration>
I am trying to execute a validation function when user clicks on Next Button on InputParameters Dialogue.
My all other custom actions work find which are included in InstallExecuteSequence.
If I use a VBScript to display a popup using following customAction instead of above function ValidateParametersFunc then that works fine.
<CustomAction Id="ValidateEnrollmentParameters" Script="vbscript" Execute="immediate"> <!CDATA[msgbox "You clicked?"]]></CustomAction>
But I want to execute the function ValidateParametersFunc.
I am getting error:
Action 18:58:13: ValidateParametersFunc.
Action start 18:58:13: ValidateParametersFunc.
MSI (c) (C4:20) [18:58:13:233]: Invoking remote custom action. DLL: C:\Users\MyUser\AppData\Local\Temp\2\MSI8187.tmp, Entrypoint: ValidateParametersFunc
MSI (c) (C4:A4) [18:58:13:236]: Cloaking enabled.
MSI (c) (C4:A4) [18:58:13:236]: Attempting to enable all disabled privileges before calling Install on Server
MSI (c) (C4:A4) [18:58:13:236]: Connected to service for CA interface.
Action ended 18:58:13: ValidateEnrollmentParameters. Return value 3.
MSI (c) (C4:04) [18:58:13:807]: Note: 1: 2205 2: 3: Error
MSI (c) (C4:04) [18:58:13:807]: Note: 1: 2228 2: 3: Error 4: SELECT `Message` FROM `Error` WHERE `Error` = 2896
DEBUG: Error 2896: Executing action ValidateParametersFunc failed.
The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2896. The arguments are: ValidateParametersFunc, ,
Target framework for CustomActions project is : v4.6.1
Can someone please help?
I have tried everything given on the internet but still not able to figure out how to fix this.

Error on linking custom actions to user interface push button control

I want to trigger some custom action by clicking some button.
I get return value 1 but the custom action did not run.
This is my log:
Action start 17:09:39: CA1.
MSI (c) (08:00) [17:09:39:220]: Invoking remote custom action. DLL: C:\Users\ARKADY~1\AppData\Local\Temp\MSI87D6.tmp, Entrypoint: CustomAction1
MSI (c) (08:EC) [17:09:39:222]: Cloaking enabled.
MSI (c) (08:EC) [17:09:39:223]: Attempting to enable all disabled privileges before calling Install on Server
MSI (c) (08:EC) [17:09:39:224]: Connected to service for CA interface.
Action ended 17:09:39: CA1. Return value 1.
My custom action is:
[CustomAction]
public static ActionResult CustomAction1(Session session)
{
session.Log("Begin CustomAction1");
return ActionResult.Success;
}
As you can see no "Begin CustomAction1" entry in the logs.
My custom action Config:
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" />
<supportedRuntime version="v2.0.50727"/>
</startup>
</configuration>
From wix code declaring CA:
<Binary Id="CA" SourceFile="$(var.CustomAction1.TargetDir)$(var.CustomAction1.TargetName).CA.dll" />
<CustomAction Id="CA1" BinaryKey="CA" DllEntry="CustomAction1" Execute="immediate" Return="check"/>
UI binding:
<Control Id="ManualUpdateButton" Type="PushButton" X="14" Y="188" Width="95" Height="17" Text="Manual Update">
<Publish Event="DoAction" Value="CA1" Order="1">1</Publish>
</Control>
The custom action is running, it's just not logging anything. That's a limitation in MSI -- you can't write to the log from a custom action invoked by DoAction in the UI.

the elusive wix installer and AdvancedWelcomeEulaDlg dialog issue

I'm building a WixUI_FeatureTree type WiX installer, but I am having a slight issue where AdvancedWelcomeEulaDlg pops-up twice, even after I've agreed to the license.
The flow is simple, with an additional dialog that is displayed before the AdvancedWelcomeEulaDlg (it's an additional consent agreement page).
The flow is: WelcomeDlg --> CustomEulaDlg --> AdvancedWelcomeEulaDlg, and I have the option to go CustomizeDlg (Advanced) or VerifyReadyDlg (Install).
<Publish Dialog="CustomEulaDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
<Publish Dialog="CustomEulaDlg" Control="Next" Event="NewDialog" Value="AdvancedWelcomeEulaDlg">1</Publish>
<Publish Dialog="AdvancedWelcomeEulaDlg" Control="Advanced" Event="NewDialog" Value="CustomizeDlg">1</Publish>
<Publish Dialog="AdvancedWelcomeEulaDlg" Control="Install" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="AdvancedWelcomeEulaDlg" Order="1">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="ServiceAccountDlg" Order="2">NOT Installed OR WixUI_InstallMode = "Change"</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="3">Installed</Publish>
Once I'm at the AdvancedWelcomeEulaDlg page and I click agree, I would like for the installed to proceed with the installation, as opposed to re-appearing again. Am I not validating something? Perhaps I'm missing a step in my VerifyReadyDlg.
Any help would be appreciated. WiX is a little convoluted.
EDIT:
Action 14:00:23: EulaDlg. Dialog created
MSI (c) (A4:5C) [14:00:23:760]: PROPERTY CHANGE: Adding EULACHECK property. Its value is '1'.
Action 14:00:24: AdvancedWelcomeEulaDlg. Dialog created
MSI (c) (A4:5C) [14:00:25:019]: PROPERTY CHANGE: Adding LicenseAccepted property. Its value is '1'.
Action ended 14:00:25: WelcomeDlg. Return value 1.
MSI (c) (A4:B8) [14:00:25:645]: Doing action: AdvancedWelcomeEulaDlg
Action 14:00:25: AdvancedWelcomeEulaDlg.
Action start 14:00:25: AdvancedWelcomeEulaDlg.
Action 14:00:25: AdvancedWelcomeEulaDlg. Dialog created
Action ended 14:00:26: AdvancedWelcomeEulaDlg. Return value 1.
MSI (c) (A4:B8) [14:00:26:336]: Skipping action: MaintenanceWelcomeDlg (condition is false)
MSI (c) (A4:B8) [14:00:26:336]: Skipping action: ResumeDlg (condition is false)
MSI (c) (A4:B8) [14:00:26:336]: Doing action: ProgressDlg
Action 14:00:26: ProgressDlg.
Action start 14:00:26: ProgressDlg.
Action 14:00:26: ProgressDlg. Dialog created
Action ended 14:00:26: ProgressDlg. Return value 1.
MSI (c) (A4:B8) [14:00:26:362]: Doing action: ExecuteAction
Action 14:00:26: ExecuteAction.
Action start 14:00:26: ExecuteAction.
This is old, but I'm adding this in case someone else runs into it.
I've been trying to show the WelcomeDlg before the AdvancedWelcomeEulaDlg, but adding NewDialog to the the publish call was making it appear twice. By ending the welcome dialog, the advanced EULA only appears once.
<!--This is after copying the WixUI_UIAdvanced.wxs and modifying-->
<!--Publish action added to close WelcomeDlg on Next rather than NewDialog the EULA-->
<Publish Dialog="WelcomeDlg" Control="Next" Event="EndDialog" Value="Ignore">NOT Installed</Publish>
<!-- ... -->
<InstallUISequence>
<!--Adding the 1 condition, makes it show even when not in maintenance-->
<Show Dialog="WelcomeDlg" After="MigrateFeatureStates" >1</Show>
</InstallUISequence>
I'm still getting a feel for WiX/MSI, but from looking at the source, it looks like since they're calling the show before ProgressDlg, welcome shouldn't open it.
<InstallUISequence>
<Show Dialog="AdvancedWelcomeEulaDlg" Before="ProgressDlg">NOT Installed</Show>
</InstallUISequence>

WiX: "PushButton: 'Next' of Dialog: 'InstallDirDlg' does not have an event defined in the ControlEvent table. It is a 'Do Nothing' button."

I have a WiX 3.8 installer Product.wxs that builds correctly in Visual Studio 2010 Professional.
I just wanted to modify the steps workflow of the installer, so I added this just after the Wix/Product/Package XML element:
<UI>
<Publish Dialog="WelcomeDlg"
Control="Next"
Event="NewDialog"
Value="InstallDirDlg"
Order="2">1</Publish>
<Publish Dialog="InstallDirDlg"
Control="Back"
Event="NewDialog"
Value="WelcomeDlg"
Order="2">1</Publish>
</UI>
Problem: WiX now fails with this message:
Error 13 ICE17: PushButton: 'Next' of Dialog: 'InstallDirDlg' does not have an event defined in the ControlEvent table. It is a 'Do Nothing' button. C:\src\wix38\src\ext\UIExtension\wixlib\InstallDirDlg.wxs 14 1 Installer
What am I doing wrong?
I think you need a reference to the WiX UI you are modifying. Try this:
<UI>
<UIRef Id="WixUI_InstallDir" /> <!-- Added line -->
<Publish Dialog="WelcomeDlg"
Control="Next"
Event="NewDialog"
Value="InstallDirDlg"
Order="2">1</Publish>
<Publish Dialog="InstallDirDlg"
Control="Back"
Event="NewDialog"
Value="WelcomeDlg"
Order="2">1</Publish>
</UI>
I want to integrate InstallDirDlg to custom UI so I copied and modified Publish statements from WixUI_InstallDir.wxs source code.
This is for all the people who are running into the same error but using the "WixSharp" libraries.
You can use the below sample code. Hope it helps!
public void GenerateMSI()
{
//generic setup code
Project project =
new Project("myinstaller.msi",
new Dir(#"d:\deployhere\", new Files(#"c:\mybuildfilesarehere\")),
new Dir(#"d:\deployheretoo\", new Files(#"c:\mybuildfilesarehere\")));
project.ProductId = new Guid();
project.GUID = new Guid();
//#1
project.UI = WUI.WixUI_InstallDir;
//#2 - this will error without #1 (Exepected Error: #3, see below.)
project.CustomUI =
new DialogSequence()
.On(NativeDialogs.WelcomeDlg, Buttons.Next,
new ShowDialog(NativeDialogs.InstallDirDlg))
.On(NativeDialogs.InstallDirDlg, Buttons.Back,
new ShowDialog(NativeDialogs.WelcomeDlg));
Compiler.BuildMsi(project);
}
#3 - ErrorMessage: error LGHT0204 : ICE17: PushButton: 'Next' of Dialog: 'InstallDirDlg' does not have an event defined in the ControlEvent table. It is a 'Do Nothing' button.
//ICE17: PushButton: 'ChangeFolder' of Dialog: 'InstallDirDlg' does not have an event defined in the ControlEvent table. It is a 'Do Nothing' button.

WiX: Checking INSTALLDIR is empty

I'd like to check that the installation directory the user has selected is empty (so that, for example, they don't try to install the app into their desktop directory, instead of a folder in there). So far, I've got a custom executable that aborts the installation with a very confusing error message, right around the point the cost gets finalized. I'd rather just prevent the user from continuing past the customization step, though.
Nothing related seemed to be on here; there's a few messages without useful answers on wix-users# too.
I did this with WiX custom action in a DLL as well. Here is the code:
WiX:
<Binary Id="CustomAction" SourceFile="$(var.SourceBinFolder)\MyCustomAction.CA.dll" />
<CustomAction Id="CheckFolderCustomAction" BinaryKey="CustomAction" DllEntry="CheckFolder" />
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="CheckFolderCustomAction" Order="2">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="3">InstallDirOk = "1"</Publish>
Custom Action:
public class CustomActions
{
[CustomAction]
public static ActionResult CheckFolder(Session session)
{
string installDir = session["INSTALLFOLDER"];
installDir = installDir.Trim();
session["InstallDirOk"] = "1";
if (Directory.Exists(installDir) && Directory.EnumerateFileSystemEntries(installDir, "*", SearchOption.TopDirectoryOnly).Any())
{
if (DialogResult.No == MessageBox.Show(
string.Format("Selected folder \"{0}\" is not empty. This might cause existing files to be overwritten. Do you want to proceed?", installDir),
"Please confirm",
MessageBoxButtons.YesNo))
{
session["InstallDirOk"] = "0";
}
}
return ActionResult.Success;
}
}
For what it's worth: ended up writing a WiX custom action in a DLL, where I can access the install session and set properties. Ugly solution; I still think there should be built-in things that do this... I just can't find it.
For those interested, relevant changeset is here.