In my WiX install package I define a property, then define a textbox that uses this property, then pass this property to my custom action. But inside of the custom action I find out that the property has it's default value, not the one I've specified in the textbox. How can I fix that?
<Property Id="DataSource" Value="."/>
<Control Id="DataSourceText" Type="Edit" Text="." Height="17" Width="150" X="200" Y="18" Property="DataSource"/>
then later in the code
<CustomAction Id="SetCustomActionDataValue" Return="check" Property="CreateDatabase" Value="DataSource=[DataSource]" />
<CustomAction Id="CreateDatabase" BinaryKey="Binary1" DllEntry="CreateDatabase" Execute="deferred" Return="ignore"/>
<InstallExecuteSequence>
<Custom Action='SetCustomActionDataValue' After="InstallFiles"/>
<Custom Action='CreateDatabase' After="SetCustomActionDataValue">NOT Installed AND NOT PATCH</Custom>
</InstallExecuteSequence>
Any properties that you intend to modify in the UI sequence and use in the Execute sequence must be Secure Custom Properties.
Related
I would like to alter text in ExitDialog depending on result of an immediate action, executed after InstallFinalize. I have tried to do this with the use of property to be set by the action (ISSUCCEEDED in the snippet below), but as I understand it, installer lost this property after the transition from server to client phase. If so, how this could be done?
<!-- The MyAction sets the property ISSUCCEEDED -->
<CustomAction Id="MyAction" BinaryKey="..." DllEntry="..."/>
<InstallExecuteSequence>
<Custom Action="MyAction" After="InstallFinalize">...</Custom>
</InstallExecuteSequence>
<UI>
<Dialog Id="MyExitDialog" ...>
...
<!-- ISSUCCEEDED is lost by now -->
<Control Id="C1" Type="Text" Hidden="yes" Text="!(loc.Text1)"...>
<Condition Action="show">ISSUCCEEDED</Condition>
</Control>
<Control Id="C2" Type="Text" Hidden="yes" Text="!(loc.Text2)"...>
<Condition Action="show">NOT ISSUCCEEDED</Condition>
</Control>
...
</Dialog>
</UI>
I have following Fragment to define my CustomActions (actually 2 methods in my CA-project)
<Fragment>
<Binary Id="FooAssembly"
SourceFile="Foo.CA.dll" />
<CustomAction Id="Action1"
BinaryKey="FooAssembly"
DllEntry="Action1" />
<CustomAction Id="Action2"
BinaryKey="FooAssembly"
DllEntry="Action2" />
</Fragment>
My Action1 looks like this:
[Microsoft.Deployment.WindowsInstaller.CustomAction]
public static ActionResult Action1(Microsoft.Deployment.WindowsInstaller.Session session)
{
session["value1"] = "some value";
session["value2"] = "some value";
return ActionResult.Success;
}
Now I need to run this CustomAction when my dialog is showing and bind the value value1 to a Edit-control like so:
<Dialog Id="FooDlg">
<Control Id="FooEdit"
Type="Edit"
Text="[value1]"
Property="value1"
Disabled="yes" />
</Dialog>
My InstallUISequence looks like this
<InstallUISequence>
<Show Dialog="FooDlg"
After="CostFinalize" />
</InstallUISequence>
I am using an Edit-control here, because I need some border - which Text is missing - and therefore I need to have the attribute Property filled.
How can I achieve this?
I have solved this by adapting my InstallUISequence like
<InstallUISequence>
<Custom Action="Action1"
After="CostFinalize" />
<Show Dialog="FooDlg"
After="Action1" />
</InstallUISequence>
I use following configuration to start my server after installation of application:
<InstallExecuteSequence>
<Custom Action='LaunchApplication' After='InstallFinalize'/>
</InstallExecuteSequence>
<Property Id="WixShellExecTarget" Value="[#startServer.vbs]" />
<CustomAction Id="LaunchApplication"
BinaryKey="WixCA"
DllEntry="WixShellExec"
Execute="immediate"
Impersonate="yes" />
Installer executes script startServer.vbs at the end of installation procedure.
What property Id should I use if I need to execute several custom actions?
For example if I will use following configuration. What property Id should I use for StopApplication custom action?
<InstallExecuteSequence>
<Custom Action='LaunchApplication' After='InstallFinalize'/>
<Custom Action='StopApplication' Before='InstallValidate'/>
</InstallExecuteSequence>
<Property Id="WixShellExecTarget" Value="[#startServer.vbs]" />
<CustomAction Id="LaunchApplication"
BinaryKey="WixCA"
DllEntry="WixShellExec"
Execute="immediate"
Impersonate="yes" />
<Property Id="???" Value="[#stopServer.vbs]" />
<CustomAction Id="StopApplication"
BinaryKey="WixCA"
DllEntry="WixShellExec"
Execute="immediate"
Impersonate="yes" />
UPDATE:
There is error "There is a problem with this Windows Installer package. A script required for this install to complete could not be run." during installation if I use following configuration:
<InstallExecuteSequence>
<Custom Action='StartServerCustomAction' After='InstallFinalize'/>
</InstallExecuteSequence>
<Binary Id='StartServerScript' SourceFile='startServer.vbs' />
<CustomAction Id='StartServerCustomAction' BinaryKey='StartServerScript' JScriptCall='startServerSub' Return='check' />
startServer.vbs
Public Function startServerSub()
Return 0
End Function
I have several properties to set when ALLUSERS is 1:
<CustomAction Id="CA1" Property="InstallDir" Value="[MYINSTALLDIR]" Execute="immediate" />
<CustomAction Id="CA2" Property="Version" Value="2.0" Execute="immediate" />
<CustomAction Id="CA3" Property="x" Value="x" Execute="immediate" />
<CustomAction Id="CA4" ... />
<CustomAction Id="CA5" ... />
<InstallExecuteSequence>
<Custom Action="CA1" After="AppSearch">ALLUSERS=1</Custom>
<Custom Action="CA2" After="AppSearch">ALLUSERS=1</Custom>
<Custom Action="CA3" After="AppSearch">ALLUSERS=1</Custom>
<Custom Action="CA4" After="AppSearch">ALLUSERS=1</Custom>
<Custom Action="CA5" After="AppSearch">ALLUSERS=1</Custom>
</InstallExecuteSequence>
This is working but I'm wondering if there is more concise way instead of tons of CAs and stupid IDs, something like:
<CustomAction Id="CA" Property="InstallDir=[MYINSTALLDIR]; Version=2.0; x=x; y=y; z=z ..." Execute="immediate" />
<InstallExecuteSequence>
<Custom Action="CA" After="AppSearch">ALLUSERS=1</Custom>
</InstallExecuteSequence>
Is this possible?
You could write a C++ custom action that calls MsiSetProperty() a bunch of times. There will technically be more risk for failure though. Once setup, a bunch of set property CA's is usually not that horrible.
I have a WiX file that includes this snippet:
<CustomAction Id="DownloadCache" FileKey="CACHEDOWNLOADER.EXE" ExeCommand="/v" Execute="deferred" Return="ignore"/>
<UI>
<Dialog Id="ExitDialog" Title="Product Installer" Height="60" Width="250">
...
</Dialog>
<Dialog Id="FatalErrorDialog" Title="Product Installer" Height="60" Width="250">
...
</Dialog>
<TextStyle Id="DefaultFont" FaceName="Arial" Size="10" />
<Property Id="DefaultUIFont" Value="DefaultFont" />
<InstallUISequence>
<Custom Action="DownloadCache" After="ExecuteAction">(NOT Installed) AND (Not REMOVE)</Custom>
<Show Dialog="ExitDialog" OnExit="success" />
<Show Dialog="FatalErrorDialog" OnExit="error" />
</InstallUISequence>
</UI>
<InstallExecuteSequence>
<Custom Action="DownloadCache" After="WriteRegistryValues">(NOT Installed) AND (Not REMOVE)</Custom>
</InstallExecuteSequence>
The issue is, the resulting .MSI does NOT contain an InstallUISequence table.
I went through the tutorial Events and Actions and the above seems correct. I'm definitely missing something here. How can I fix it?
There must be more than meets the eye here. Even the simplest fragment below will generate an InstallUISequence table with the bare minimum actions of ValidateProductID, CostInitialize, FileCost, CostFinalize and ExecuteAction. No actual UI elements per se, but that's another issue.... (Are Dialogs Optional Now??)
<Wix...>
<Product...>
<Package.../>
</Product>
</Wix>