Events and Actions
This is the third part of a series on using Wix 3.7 with
Visual Studio 2012. Previously I walked through the Wix tutorial (http://wix.tramontana.co.hu/tutorial/
) from “Getting Started” through “Putting it to Use” and then through the User
Interface section from “First Steps” through “New Link in the Chain” to add
some user interface dialogs including a custom dialog to our installer. Now I
want to walk through creating a custom action to our install sequence.
Queueing Up
The Windows Installer runs through a series of actions
specified in the .msi database. The tutorial mentions using the .msi editor
Orca to investigate the sequence. Orca is a must-have tool for doing installer
development. WiX has four tags to change the sequence of the events, suppress
events and add additional events including custom ones: AdminUISequence,
AdminExecuteSequence, InstallUISequence and InstallExecuteSequence. Changing
this sequence is beyond the scope of what I want to do for now.
Extra Actions
Custom Actions need to be added as a child of the Product
element in Wix. Additionally if you want the action to run within the install
sequence you need to add it to one of the appropriate tags mentioned in
Queueing Up. The tutorial describes using custom actions to do things like
execute applications, set properties and display errors. There are also a number of additional
standard actions that can be queued up using a tag like InstallExecuteSequence.
What’s Not in the Book
I am going to have a user action that references a custom
action I write. Following the tutorial’s lead, this action is going to check
the validity of the product key entered by the user. To add the code file for this we right-click
the solution and Add > New Project.
Under Windows Installer XML select the C# Custom Action Project. We’ll
call it CheckPID.
Wix adds the code file and stubs out the custom action. It
also adds a config file with the necessary supportedRuntime tags included. I
add my code to retrieve the PIDKEY property from the installer session. Then it
writes the PIDACCEPTED value back to the session based on whether the PIDKEY
that the user inputs stats with a “1” or not: the value is 1 if it does and 0
if it does not. Then our action is always going to return ActionResult.Success.
If we returned a failure the installer would give the user an error and shut
down. We want them to be able to stay at the dialog and insert the correct key.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Deployment.WindowsInstaller;
namespace CheckPID
{
public class CustomActions
{
[CustomAction]
public static ActionResult CheckPID(Session session)
{
string Pid = session["PIDKEY"];
session["PIDACCEPTED"] = Pid.StartsWith("1") ? "1" : "0";
return ActionResult.Success;
}
}
}
We also need to add a reference from the Wix project to our
CheckPID project. Right-click on the References item under the Wix project and
do Add Reference and then select our new project from the Projects tab.
In the Product.wxs file I added a new Fragment that contains
the CustomAction tag and the binary reference to the DLL to use. The SourceFile
attribute of the Binary element is the source file where the action is. The
CustomAction element then references the Binary element by Id. The DllEntry
attribute of the CustomAction is the method of the binary that will be called.
<Fragment>
<CustomAction Id='CheckingPID' BinaryKey='CheckPID.CA' DllEntry='CheckPID' />
<Binary Id='CheckPID.CA' SourceFile='..\CheckPID\bin\Debug\CheckPID.CA.dll' />
</Fragment>
How to Manage
Notice above that the DLL we are referencing is not the
expected CheckPID.dll. Wix uses the MakeSfxCA (for Make self-extracting custom
action) utility to put a wrapper around the assembly our C# code creates to
have a managed custom action. If you use the Wix Custom Action project as
described above Wix will handle making that call to MakeSfxCA. If you just
create a C# code library file you will need to add a post-build call to create
that wrapper (http://wix.tramontana.co.hu/tutorial/events-and-actions/how-to-manage).
Control Your Controls
In the UserRegistrationDlg I replaced the Publish events
with new ones.
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="&Next">
<Publish Event="DoAction" Value="CheckingPID">1</Publish>
<Publish Event="SpawnDialog" Value="InvalidPidDlg">PIDACCEPTED = "0"</Publish>
<Publish Event="NewDialog" Value="SetupTypeDlg">PIDACCEPTED = "1"</Publish>
</Control>
The first Event DoAction has a value that refers back to the
Id of our CustomAction. Then we check the PIDACCEPTED value that we set in our
code. If the product Id is not accepted we are going to spawn a new dialog,
InvalidPidDlg. If it is accepted we’ll advance to the CustomizeDlg dialog as
before. Note that SpawnDialog creates a child dialog to the current dialog.
NewDialog navigates to a new dialog.
As before when I added the User Registration dialog I add a
new Wix .wxs file to the Wix project named InvalidPidDlg.wxs. To this file I
added a UI container with the new dialog. The dialog contains the Error text to
convey to the user, an exclamation point icon and a PushButton that will close
the dialog sending us back to the parent UserRegistrationDlg dialog for us to
re-enter the key. I also added the binary reference to the exclamation icon to
include. You can get Exclam.ico from the tutorial files download (http://wix.tramontana.co.hu/system/files/samples/SampleAskKey.zip)
or create your own.
xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Dialog Id="InvalidPidDlg" Width="260" Height="85" Title="[ProductName] Setup" NoMinimize="yes">
<Control Id="Icon" Type="Icon" X="15" Y="15" Width="24" Height="24"
ToolTip="Information icon" FixedSize="yes" IconSize="32" Text="Exclam.ico" />
<Control Id="Return" Type="PushButton" X="100" Y="62" Width="56" Height="17" Default="yes" Cancel="yes" Text="&Return">
<Publish Event="EndDialog" Value="Return">1</Publish>
</Control>
<Control Id="Text" Type="Text" X="48" Y="10" Width="194" Height="45" TabSkip="no">
<Text>
The user key you entered is
invalid.
Please, enter the key printed on
the label
of the jewel case of the
installation CD.
</Text>
</Control>
</Dialog>
</UI>
<Binary Id="Exclam.ico" SourceFile="Exclam.ico" />
</Fragment>
</Wix>
In
Conclusion
You should be able to build and run the installer now.
Submitting a product key that starts with anything other than a ‘1’ will
display the Invalid PID dialog. As I use
WiX for our real-world cases I will post anything interesting or sticking
points that come up.
5 comments:
Hello,
I have a problem that when the custom action has a reference to another X.DLL (reference created inside visual studio 2012, custom action project)then during the installation, the error is always: X.DLL FileNotFound Exception. Do you have any suggestion ?
Try these suggestions. I haven't tried doing that yet, but I would like to know if either of these or some other solution worked for you.
http://stackoverflow.com/questions/1591700/how-to-execute-a-wix-custom-action-dll-file-with-dependencies
http://stackoverflow.com/questions/4549498/wix-installer-custom-actions-ca-which-require-an-external-library-cant-find-i
Hi, Ben
I am trying to run your sample and got error:
Error 4 ICE17: PushButton: 'Back' of Dialog: 'SetupTypeDlg' does not have an event defined in the ControlEvent table. It is a 'Do Nothing' button. C:\src\wix38\src\ext\UIExtension\wixlib\SetupTypeDlg.wxs 25 1 KevinSetupTest
Do you have any suggestion?
Thanks
Hi,
I need to show Wpf screen while installing, for e.g: when you install WIX3.7 you can see an UI, and please provide your source code , it will be very usefull.Kindly try to give an article about BootStrapper application, Thanks a lot for your article
HI, I have tried to call to CustomActions and work fine. My Problem is that in the CustomActions method, i want to call a web service. I made a reference to it, but it does not work. How can I make a call to a Web Service? thanks
Post a Comment