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.
Related
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
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" />
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.
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.
I'm making an installer which must configure a web service it installs. It dynamically generates properties which hold the data collected from the user in the UI sequence, installs the service and sets the parameters.
SetParams CA uses dynamic properties generated in the UI sequence. To access data in deferred CA, I've created an immediate CA which dynamically extracts session data and puts it in the CustomActionData.
<CustomAction Id='SaveParams' BinaryKey='Setup.CustomAction' DllEntry='SaveParameters' Execute='immediate' Return='check'/>
<CustomAction Id='SetParams' BinaryKey='Setup.CustomAction' DllEntry='SetParameters' Execute='deferred' Impersonate='no' Return='check' />
<Custom Action='SaveParams' Before='SetParams'><![CDATA[REMOVE <> "ALL"]]></Custom>
<Custom Action='SetParams' Before='InstallFinalize'><![CDATA[REMOVE <> "ALL"]]></Custom>
Following is the part of SaveParameters method in the custom action
customActionData.Append(string.Format(CultureInfo.InvariantCulture, "{0}={1};", propertyName, session[propertyName]));
This approach works!
When started from admin cmd session[propertyName] returns the correct value, but when I run the installer change from non-elevated cmd prompt, I cannot access the property values in the immediate CA - session[propertyName] returns empty string ?!
I can access the (static) property defined in wxs file
<Property Id="INSTALL" Secure="yes" />
but not the one's I've added in some other immediate custom action in the UI sequence like this
session[property] = "VALUE"; //eq. property = DATABASENAME
Does anyone have any idea why I cannot read the dynamic public property value?
NOTE: Spin off from this question.
There are two options for resolving this issue.
1. Immediate action which reads properties to be moved from execution sequence to UI sequence
2. Actions in execution phase can access data from secure properties as stated in the question.
If the properties are dynamically created in CA, they must be added to SecureCustomProperties system property. Separator char is ';'.