How to define a CustomAction with a long command line in WIX? - wix

I have define a custom action in my wxs file:
<CustomAction ExeCommand="long command line" FileKey="xyz.exe" Id="foo"/>
and I receive the warning:
warning LGHT1076 : ICE03: String overflow (greater than length
permitted in column); Table: CustomAction, Column: Target, Key(s):
What is the right solution to define an action with a long command line?

After many time I have find a solution. I split the command line into multiple properties.
<CustomAction Id="action.prop0" Property="prop0" Value="first part with [INSTALLDIR]"/>
<CustomAction Id="action.prop" Property="prop" Value="[prop0] second part"/>
<CustomAction ExeCommand="[prop]" FileKey="service.exe" Id="myaction"/>
<InstallExecuteSequence>
<Custom Action="action.prop0" After="InstallFiles"/>
<Custom Action="action.prop" After="action.prop0"/>
<Custom Action="myaction" Before="InstallFinalize"/>
</InstallExecuteSequence>

Assign the long command line to a property and then use [PROPERTY] in the custom action. Although EXE custom actions in general are frowned upon. If you must do it use the WiX Quiet Execute Custom Action feature.

Related

WiX customaction doesnot have value for session.Property["CustomActionData"]

I have to pass a value to my custom action in patch release for my feature. I did some research and did the following:
<CustomAction Id="CustomAction1" Property="customaction2" Value="Value1" />
<CustomAction Id="customaction2" BinaryKey="Binary.dll"
DllEntry="Functionname" Impersonate="no"
Execute="immediate" Return="check" />
I also updated the installExecuteSequence as below:
<Custom Action='CustomAction1' After="InstallFinalize"><![CDATA[PATCH]]></Custom>
<Custom Action='customaction2' After="CustomAction1"><![CDATA[PATCH]]></Custom>
I also added the componentrefs to the patch.wxs file.
<CustomActionRef Id="CustomAction1.PackageGuid"/>
<CustomActionRef Id="customaction2.PackageGuid"/>
To access this parameter value, I tried the following code in my customaction "Functionname" :
var value = session.Property["CustomActionData"];
The "value" is Empty. I did some debugging and found that, i am getting the value from below code:
var value = session.Property["customaction2.PackageGuid"];
I have not seen any examples that access properties with packageGuids also. I am not sure why the first approach(using "CustomActionData") is not working for me.
Can you guys let me know what i am missing?
Also, Is there any harm in using with packageGuids? If not, i am planning to continue this way. Please let me know if you need me to try any other st

Wix installer - copy attribute value to another attribute

What I want to do is copy the value of a single property, and place it as the value of another property. Is this possible with Wix?
<Property Id="PROP1" Value="default" Secure="yes"/>
I want PROP2 to have the same value some where during the UI sequence.
You can use Custom action to accomplish it. Define action as
<CustomAction Id="SetMyProperty" Execute="immediate" Property="PROP2" Value="[PROP1]" />
Then call it in <InstallUISequence> or <InstallExecuteSequence> when you need it set, something like
<Custom Action="SetMyProperty" After="FileCost"></Custom>
Although #Mischo5500 answer is correct, there is a more elegant way to achieve the same. You can use a special element, <SetProperty>, which was designed exactly for that purpose.
The benefits of using it is:
It's just one line of WiX code
It is scheduled properly by default into both sequences
The name of the element is more natural and self-explanatory
Thus, the above example can be transformed into the following:
<SetProperty Id="PROP2" Value="[PROP1]" After="FileCost" />

WiX - commit more than one Property to deferred Custom Action

I have a problem with my WiX installer in contact with deferred / immediate custom actions. Please excuse my english.
I want to surrender some properties, entered by the user, to a deferred custom action. I know that I need a immediate custom action and "CustomActionData" to do that. I´ve implement it at this way.
The binary:
<Binary Id='myAction' SourceFile='.\TemplateGeneration.CA.dll'/>
The immediate custom action:
<CustomAction Id='Datenuebergabe' Property='DoSomething' Value='InstalllocVar=[INSTALLLOCATION]'/>
The deferred custom action:
<CustomAction Id='TemplateGenerationInstallKey' BinaryKey ='myAction' DllEntry='DoSomething' Impersonate='no' Execute='deferred' Return='check' HideTarget='yes'/>
The InstallExecuteSequence
<InstallExecuteSequence>
<Custom Action="Datenuebergabe" Sequence="1399"/>
<Custom Action="TemplateGenerationInstallKey" Before="InstallFinalize"/>
</InstallExecuteSequence>
Calling the property in the deferred custom action:
string somedata = session.CustomActionData["InstalllocVar"];
TemplateEngineCall(somedata+"templates", "install_key_cmd", somedata+"scripts", "install_key.cmd");
My problems:
If I try to install my program it breaks.
With this code i only can surrender one property, but I need to commit more than one.
For information:
When I have a look at the log file, there´s a System.Collections.Generic.KeyNotFoundException while the custom action call.
Why doesn´t this work?
Well, I need the deferred custom action to write into the "program files folder". Because of the needed rights, the deferred custom action is required and the immediate custom action executed before the deferred should help to handle the properties. Is it possible to do that?
I hope you understand what are my problems and possible you can try to help me.
First of all, there's a mistake in the way you pass the data from immediate custom action to the deferred one. The name of the Property you use in the immediate custom action must be exactly the same as the Id of the deferred custom action. In your case:
<!-- immediate CA -->
<CustomAction Id='Datenuebergabe' Property='DoSomething' Value='InstalllocVar=[INSTALLLOCATION]'/>
<!-- deferred CA -->
<CustomAction Id='DoSomething' BinaryKey ='myAction' DllEntry='DoSomething' Impersonate='no' Execute='deferred' Return='check' HideTarget='yes'/>
This will resolve the problem with KeyNotFound exception.
Now, back to your question how to pass more than 1 value.
First, in the immediate CA use ; separator to pass the name-value collection, like this:
<CustomAction Id="SetForDoSomething" Return="check" Property="DoSomething" Value="source=[ArchiveFolder][ARCHIVENAME];target=[WebsiteFolder]"/>
As you can see, there are 2 name-value pairs we pass to the deferred CA here, source and target. In the deferred CA, use the following code to take those values out:
var source = session.CustomActionData["source"];
var target = session.CustomActionData["target"];
And that's it.

Set property value based on condition in WiX

I searched through several questions at Stack Overflow, but nothing helped me. The problem is:
I look in the registry for some value (I know how to do that). I know how to set property. But I cannot find the way how to write this expression in WiX. This is what I want to write in pseudocode:
if(registryvalue contains substring1)
set property to value1
if(registryvalue contains substring2)
set property to value2
This condition must be evaluated at runtime. Is there a way to write this condition? What would some sample code look like?
You can use a type 51 custom action to set the property:
<CustomAction Id="SET_VALUE1" Property="TEST_PROPERTY" Value="value1" />
<CustomAction Id="SET_VALUE2" Property="TEST_PROPERTY" Value="value2" />
Use the condition when you call the custom action in install sequences:
<Custom Action="SET_VALUE1" After="AppSearch">Not Installed AND (REG_VALUE="substring1")</Custom>
<Custom Action="SET_VALUE2" After="AppSearch">Not Installed AND (REG_VALUE="substring2")</Custom>
Or you can write the custom actions in managed code like C#, and schedule it after AppSearch in case you have many comparisons.

Execute a custom action before Product condition

Basically I need to verify that a certain program is not running before installation. This is done via a custom action, which sets a property, APPRUNNING:
<CustomAction Id="CheckingAppIsRunning"
BinaryKey="AppIsRunning"
DllEntry="AppIsRunning"/>
<Binary Id="AppIsRunning"
SourceFile="CustomActions.CA.dll" />
But in the message displayed, APPRUNNING seems to be null, that is, it's not set at all (should be either "0" or "1").
<Condition Message="Exit all instances of [APPNAME] before installation (APPRUNNING = [APPRUNNING]).">
<![CDATA[APPRUNNING = "0"]]>
</Condition>
<InstallExecuteSequence>
<Custom Action="CheckingAppIsRunning" Before="LaunchConditions" />
</InstallExecuteSequence>
I suppose the custom action is not executed at the moment of the condition check. What are the options to perform a condition check after a custom action?
The LaunchConditions action is scheduled to run in both InstallUISequence and InstallExecuteSequence. As long as you schedule your custom action to InstallExecuteSequence only, the property won't be set by the time LaunchConditions is fired in InstallUISequence.
You should schedule your CheckingAppIsRunning custom action in both sequences. You might also want to define it with Execute='firstSequence' attribute - this way it will run the first sequence it is met in.
This is what I mean, actually:
<InstallUISequence>
<Custom Action="CheckingAppIsRunning" Before="LaunchConditions" />
</InstallUISequence>
<InstallExecuteSequence>
<Custom Action="CheckingAppIsRunning" Before="LaunchConditions" />
</InstallExecuteSequence>
And the definition:
<CustomAction Id="CheckingAppIsRunning" BinaryKey="AppIsRunning" DllEntry="AppIsRunning" Execute="firstSequence"/>