The intended behavior of each custom action must be documented for the Windows logo program.
In InstallShield, custom actions are documented using the ISCustomActionReference table.
I am now using WiX to create my installs, how should custom actions be documented using WiX?
There's no reason you can't do the same - you can create a custom table in the MSI file with WiX and add your docs there. The docs typically emphasize custom tables to be used as data for custom actions, so maybe they're harder to find. There's an example here of a custom table WiX element if you scroll down:
How Best to Define a Custom Action
Related
How can I get a path to file being installed from a WiX custom action?
I'm creating a WIX Extension, which has a custom element which can be nested under <File> component like this:
<Component Id="FooComponent">
<File Id="filekey" Name="foo.txt">
<myextension:Stuff />
</File>
</Component>
The extension has its custom table which has a foreign key columns pointing to "Component" and "File" tables, and it is executed when a file's component is being installed/uninstalled (like the built-in IIS extension or SQL extension for example)
What I want to achieve is, in my deferred (sheduled) custom action, figure out the target path of the file the extension isbound to. I.e. basically in the differed custom action, I want to get value of [!filekey] (in terms of MSI formatted string). How can I go about that?
I have found a somewhat similar topic here
One of the solutions suggested was to use MsiFormatRecord from a custom action and pass that [#filekey] to that function. It resolves properly then.
I've found examples of using this approach in WiX sources, in gaming extension and NetFX extensions; they use code like this:
StrAllocFormatted(&pwzFormattedFile, L"[#%s]", pwzFileId);
WcaGetFormattedString(pwzFormattedFile, &pwzGamePath);
Here WcaGetFormattedString is basically a wrapper for MsiFormatRecord
Still unanswered, is this a right approach to the issue?
Basically you pass that [!filekey] to the deferred custom action in that format, using the CustomActionData indirect way of doing that. Then in your custom action you get the property value [CustomActionData] . This might help:
How to pass CustomActionData to a CustomAction using WiX?
To spell it out, if your type 51 custom action that is used to prepare CustomActionData has a Target of [!filekey] then when you retrieve the value of the CustomActionData property inside your custom action then it will contain the full path to the file, the entire path and filename. This demonstrably works, although it wouldn't be practical if you were doing this for many files.
is it possible to set a property in Deferred custom action.If so please suggest me the way ?
I had similar dilemma few weeks back. And this is what was told to me by seniors.
Deferred Custom action cannot directly modify installer properties.
But there is an workaround: you can use immediate custom action to set the property.Also you could use CustomActionData to store property value and then use it in C# or VB.net Custom Actions.
I think this Link might help you.
We're updating some old WiX scripts to take advantage of the Feature attribute of components, so that we don't have to update the file in two places whenever we add or remove a component (once to add the Component and again to add a ComponentRef to the ComponentGroup).
We separate out WiX project into separate files, one per fragment to make things more manageable. But my fragment defining the components for a feature is no longer getting included. It sounds identical to Tomas's issue in his response to the Feature attribute announcement. But while he is using Heat to auto-generate his Wix file, we're manually crafting them from scratch.
I tried creating a dummy property in the fragment's .wxs file and then referencing it in the main .wxs within the Product element. The fragment was still not included and I got an invalid property ID.
We initially tried using the strategy described here to reference directories in the component, but while this eliminates the need for a separate ComponentGroup full of ComponentRefs, it also separates my component definition from the directory tree definition, which kind of defeats the purpose of only needing to look in one place to do an update.
Will I need to pull all of my fragments into the main Product.wxs file simply to take advantage of the Feature attribute, and avoid having to update the file in two places per component? Or is there an easy way to get the fragment to include? Again using a dummy property reference didn't seem to work.
Edit: I think I found the issue in my build--I had defined a Directory under the Product Tag and then a DirectoryRef in the Fragment, rather than the other way around.
Take a look at how we authored the WiX setup itself: Author Components under ComponentGroups and use ComponentGroupRef to pull those into Features. That eliminates most duplication. You can author Directory and DirectoryRef elements in fragments in the same file as your Components/ComponentGroups.
I'm looking at using Burn as a bootstrapper for an installer and I need to pass in a couple of arguments into the MSI.
I know that the way to do this is to use MsiProperty elements, the issue I am having is with displaying the UI to capture those properties. I'm aware that I can create a completely custom UI via the managed bootstrapper application host, however this is turning out to be a lot of work to implement for a relatively minor tweak to the bootstrapper.
I've found this blog article with describes how to do basic UI customisations and wondered if its possible to modify the Burn UI to include a simple checkbox / textbox (whose value is then use to set a Burn variable so I can pass it into my MSI) in a similar way, or do I need to use the managed bootstrapper application host after all?
I cant find any documentation on this anywhere, but a little bit of experimentation + reading through the source code reveals that this is fairly straightforward - just set the Name of the control (e.g. Checkbox) to the name of a Burn variable (not a WiX variable - they are different), like so (see Burn UI Customisations for more info on where to put this)
<Checkbox Name="MyCheckBox" ...>Hello, checkbox</Checkbox>
If you like you can define a burn variable beneath your bundle to initialise it to some value (use 1 for "ticked" and 0 for "unticked" with checkboxes)
<Variable Name="MyCheckBox" Value="1" />
However its not required - the variable will be created automatically for you anyway. Note that it needs to be a Variable, not a WixVariable - these are different.
Finally to set an MSI property based on this variable add a MsiProperty element as a child of your MsiPackage element, like so
<MsiPackage Name="MyMsi.msi" ...>
<MsiProperty Name="SOMEPROPERTY" Value="[MyCheckBox]" />
</MsiPackage>
The value of the MSI property "SOMEPROPERTY" will then be set to 0 or 1 based on the checked state of your checkbox.
I am modifying an existing WiX installer to handle updating an existing installation of one of our products. There are several values whose defaults are specified in properties. These properties are displayed to the user for editing and are then written to a custom configuration file by the existing installer.
My code needs to be smart enough to detect if it is doing a brand new install versus installing an older version. If it is doing a brand new install, it needs to set the properties to default values. But if it is doing an upgrade, the code needs to retrieve the valus of those properties from the existing configuration file and display those to the user.
From the reading I've done, it seems to me I need to use a type 51 custom action to set the properties. But how do I implement this custom action?
I'm thinking that I have to first define the custom action to put it in the custom action table, and then I need to stick a tag somewhere to call it. And then I need to define it.
How can I do this? What would some example code be?
After doing some more research into custom actions, I believe I've got all of this figured out. I added a <Binary> tag to the .wxs file to identify where the custom action resides. I then referenced the Binary tag's ID in the CustomAction. Finally, I added a Custom tag to the InstallExecuteSequence section that referenced the CustomAction tag by ID.
The final Custom tag mentioned above needs to go into the InstallUISequence section, not the InstallExecuteSequence section, as the custom action needs to be called before the dialog is displayed.
As for the implementation of the Custom Action itself, I added a new C# Custom Action library project to the solution. In there, I implemented a method, decorated with the [CustomAction] attribute. This method uses the values of properties stored in the Session object passed as a parameter to the method and determines the path of the current version's executable file. It then does the work needed to locate the values in the program's Configuration file that need to be preserved across versions and writes them to other properties for the upgrade script.
Example:
[CustomAction]
public static ActionResult SetProperty(Session session)
{
try
{
session.Log("Begin SetProperty action");
session["PROPERTY_NAME"] = "value"
}
catch (Exception exception)
{
session.Log("ERROR in custom action SetProperty {0}", exception.ToString());
return ActionResult.Failure;
}
return ActionResult.Success;
}
Read the following sections of WiX tutorial:
Extra Actions: gives an overview of how to add a Custom Action to MSI;
What's Not in the Book: provides an example how to implement a Custom Action in DLL.