unattended installation wix read command line parameters passed to msiexec - wix

I am writing an installer using wix. For silent installation using msiexec, i would like to provide few parameters from the commandline which i want to set to wix properties.
These properties I am using to enable/disable few features.
Can anyone please tell me how to read those command line properties passed to msiexec.
Using C++ Custom Action we read using MsiGetProperty
Thanks a lot..
Best Regards,
Marc

To make the property available from the command line you should define it using an upper case name. I often use a launch condition to check the properties have been passed on the command line:
<Property Id="PROPNAME" Admin="yes" />
<Condition Message="Public Property PROPNAME not passed">Installed or PROPNAME</Condition>
The Installed variable only checks for the property value on install rather than uninstall.
The command line for msiexec looks like this:
msiexec -i <msiname.msi> PROPNAME="PROPVALUE"

You should also look into the ADDLOCAL property. You can probably simplify your problem with a command line like:
msiexec /i product.msi ADDLOCAL=FEATURE1,FEATURE2,FEATURE4,FEATURE5

A Feature element can use one or more Condition elements as children. A feature condition can use installer properties directly in their formatted form, for example:
[PROPERTY_NAME] = "value"
Each feature Condition element must use a Level attribute. In your case it can be 0 so the feature is not installed when the condition is met. Basically, you will set a condition for skipping the feature.

Related

WiX - passing parameter from MSI to Xeam bootstrapper application

I am using a WiX bundle with Xeam Visual Installer as a bootstrapper UI application.
What I would like to do is set some variables inside the Custom Actions that my MSI is running, and I have figured out how to do that. I can see in my logs that the variables are being set.
My problem is I hoped that I would be able to read these variable and display them on the last page of my bootstrapper UI. Out here the variables still show as empty strings.
If you are familiar with Xeam, I am trying to access them like this:
MyProp = Bootstrapper.Engine.StringVariables["MY_PROP"];
Similar to the way you read and set properties during the initial bootstrapper workflow, before everything is sent to the MSI.
Has anyone else tried to do this. Should it be possible or are there any other solutions you can suggest?
This is apparently not possible. The solution is to use the registry instead.

set TRANSFORMS argument in custom action

Can I set the TRANSFORMS argument value in the custom action within the MSI ? If Yes, need to set the custom action being called at which stage ? Thanks.
Transforms can't be applied dynamically during an installation. They have to be applied at the time the installation is started. A custom bootstrapper (EXE) could use business logic to select a transform and apply it when starting the installation.
You can also embed the mst files into the _Storages table inside the MSI, and windows will auto-detect the supported transforms for you.
https://msdn.microsoft.com/en-us/library/aa368351(v=vs.85).aspx

WIX Installer - Possible to Invoke Custom Action .exe Before `InstallFiles`?

I have an .exe embedded inside my MSI installer which I'd like to somehow call directly from the installer, before the the 'InstallFiles' action occurs.
It's defined as follows:
<CustomAction Id="LaunchInstallManager_TryUninstall" Return="ignore" Directory="INSTALLFOLDER" Execute="deferred" Impersonate="no" ExeCommand=""[#fil713F8F6A7BC9B98857D779B9B29873E1]" /someargument"></CustomAction>
<Custom Action="LaunchInstallManager_TryUninstall" Before="InstallFiles">NOT Installed</Custom>
But upon looking at the logs, it looks like it's (trying to be) called from the install destination.
Is such a thing possible?
It is possible, but in a different way. The 'run EXE' type of custom action will always search for the executable on the target system. Thus, if your executable is installed along with your app, it is not an option.
Here is another way:
First, author your EXE as a <Binary> instead.
It is as easy as <Binary Id="MyEXE" SourceFile="PATH\TO\EXE" />.
Add a DLL deferred custom action, which will extract the binary, run it with parameters and clean up afterwards.
This post can give you an idea how to extract the binary using C# and DTF. Besides, in case you need to pass parameters, make sure you do it the right way for deferred custom action.
Finally, remember that each deferred custom action (that is the one to change the target system) must have corresponding rollback action. This article might give you some hints on how to test the direct and rollback behaviors of your custom actions.

WiX: returning a value from exepackage

I have been asked to add a function to an existing WiX package.
Specifically, I need to run a small c# application and return a single int back to WiX to conditionally control further actions.
I can see from ExePackage help that there is an ExitCode, but this is an enumeration of success, error, scheduleReboot or forceReboot.
I have googled quite a bit and I am wondering if I am missing the point. I can probably implement the C# process internally within WiX to get the user to provide the information I need, but the existing package already has custom ExePackages written in C# with a particular style, so I'd like to stay with that if I can. (The existing packages don't return any needed values)
Can I do this, or do I need to try and operate entirely within WiX?
For reference, one of the existing packages looks like this:
<ExePackage
SourceFile="..."
DisplayName="License Key"
InstallSize="0"
Permanent="yes"
InstallCommand="/ignoreIfLicensed"
RepairCommand="/ignore"
UninstallCommand="/ignore"
/>
The reference to <ExePackage ...> implies you want the condition to operate in a WIX bundle. In this scenario I think your options are limited and you can only map the return value of an ExePackage to global behaviour like forceReboot.
Do you have any <MsiPackage...> references? If you have, you could move the conditional behaviour inside each <MsiPackage...> using a Custom Action to call the exe and set a property. The property can then be used as a condition in each <component...> you want to conditionally install. See Using a WiX custom action to set a property's value for more information on custom actions setting properties.

How can I get the return code from a CustomAction?

I have the following CustomAction in my project:
<CustomAction Id="InstallDriver"
Return="check"
Execute="deferred"
Impersonate="no"
FileKey="FileDriverInst"
ExeCommand="-install" />
<InstallExecuteSequence>
<Custom Action="InstallDriver" Before="InstallServices" />
</InstallExecuteSequence>
The program that installs the driver produces useful return codes, for example if the installation failed because the system needs to be restarted following a previous driver uninstall.
Currently if anything other than success is returned, I get a dialog saying 'A program run as part of the setup did not finish as expected.' and the installation fails. This is not optimal.
How can I get and handle return codes?
Windows Installer doesn't support handling custom action return values.
For an EXE custom action a non-zero return value is interpreted as an error and the installation stops. Only a win32 DLL or VBScript custom action can change the installation behavior through its return code, but it's still very limited.
If you want to reboot the machine after install, you can set the REBOOT property.
Added as an "answer" by request:
Your whole design is not optimal. It's out of process to Windows Installer and isn't declarative. There are better patterns for installing drivers.
That's simply the way MSI handles EXE calls. You'd have to write your own custom actions to wrap the EXE call and then interpret the failure reason. To me this just adds yet another failure point.
You can't get a return code from a CustomAction, but in a round about way you can set what that return code would be on a property. That might as well be the same thing as getting the return code.
You have to get it within the script/dll your custom action is performing. Otherwise, the return code only shows up in the log.
For example, if you have property like
<Property="MyCode" Secure="yes">
Then within VBScript (or Jscript) you can get the value of that property like this:
VBScript
Session.Property("MyCode")
Initially, it is null. You can set it in VBScript like this:
If someCondition = 4 Then
Session.Property("MyCode") = "4" // For a return code of 4
End If
Once back in your WiX .wxs file, if you look at the value of your property, it is now 4. You could even use it in CDATA tags.
For example, only spawn a dialog if MyCode is equal to 4.
<Publish Dialog="SpawnDialog" ...><![CDATA[ MyCode = 4 ]]></Publish>