Nigel: With a presentation on building
professional installations for Windows installer XML, please welcome
back Steve Ives. Steve: Thank you, Nigel. All right. So yeah, as Nigel says, that's what I'm going to do now is talk to you a little bit about Windows
Installer XML and how you can use it to create professional installations for
your Synergy and other applications. You know, more and more of us have made the
move to Windows now - a lot as I look around the room, there's an awful high
percentage of people who are now on the Windows platform and not too many on
Linux and VMS anymore. Still, it's still a lot of customers out there, but a lot
of you guys, seems to me, are on Windows and once you obviously get to the
Windows platform, one of the things that can be very important, particularly if
you're creating an application for resale, but even if not - even for internal
deployments, it can be pretty important to have a good installation experience
for that product. Many of us have used a variety of tools over the years to
achieve that, be it InstallShield or other products that are available
in that market space, and in recent years an alternative has come to surface and
it's actually quite a nice environment and one that's very easy to get up and
running with, and it's also free, which is very nice. So that toolset is called WiX,
it's called the Windows Installer for XML. It is as the slide says a free
software toolset, it builds basically Windows installer packages - MSI files,
essentially, or they can be wrapped up in setup.exe's as well. Based on a
definition of your product that is simply defined or expressed through XML.
So it's a very easy syntax to get up and running, you don't need any complex tools,
there are some - there is tooling available on top of it, if you
want to use those tooling, there are some commercial products that you can buy if
you want to put a UI on some of this stuff. But the basics of WiX, certainly in
terms of, you know, when you think of a typical Synergy application, and
most other applications as well, unless it's a really complex product, the
installation is largely about providing files into certain places, creating
shortcuts, maybe putting some things in the registry, maybe modifying paths, or
setting some environment variables, so it's pretty straightforward stuff much of the time and that's something - all of those things are
things that are really easy to achieve just through simple editing of XML in a
text editor or in Visual Studio. There are extensions that you can download, the toolkit that you can download does provide some Visual
Studio project templates that help you very easily put this stuff together as
well. WiX supports all of the Windows
installer features, so it's a complete implementation and it scales from the
very small list of projects, you can literally throw an installation together
for a very simple product in a few minutes, through to the very largest of
products. Microsoft themselves heavily use WiX and have done for some time. WiX
actually was Microsoft's first open-source project several years ago. Now pretty much half the stuff they do is open-source. So it did come out of
Microsoft, and WiX is the technology that they use to install Microsoft Office,
Visual Studio, SQL Server, Exchange Server, so this is a mainstream
product set and it's open-source, so it's heavily used by Microsoft and a lot of
other large software companies as well. WiX itself was created by Rob Mensching,
or a guy called Rob Mensching, who did use to work at Microsoft. He personally
worked heavily on creating the installations for Office, and Visual
Studio, and Windows, and so on, and he was also the original author of a utility
called Orca. If you've ever done any work with installations you're probably
familiar with Orca - it lets you open up an MSI file, and peek inside, and edit
things, and stuff like that, and he's widely recognized as a leading authority
on the subject of deploying software. He created WiX in 1999 and designed it
from the ground up to be very easy to use - just simple XML-based, that you don't
need any fancy tools, you simply could use Notepad, literally, if you wanted to.
It quickly got adopted throughout Microsoft and, like I say, it became
Microsoft's first open-source project. Rob now is the co-founder of a - he left
Microsoft in 2013 and founded a company called FireGiant and there they are
basically in business to put commercial tooling around WiX, and they have some add-on products if you want to put UI - deal with this stuff through UIs, they
have commercial support available, they have
consulting services available, and so on, if you want to get some
assistance. And Marty and Jeff were actually very good friends with Rob, they meet him frequently at the Microsoft events that they attend.
They're all part of the Visual Studio integration program together, so
we got a pretty good working relationship with the guy and his
company. Just a little bit about our history with with WiX and FireGiant. CodeGen's been using a WiX installer since the rewrite, since the version 5
release came out, so that's where I kind of learned what I needed to do. And
Synergy/DE itself, we're in the process as Roger mentioned the other day, of
moving to WiX-based installers. Right now, the ODBC installer is now - has now
switched over to WiX, the other ones are still being - still basically going
through the QA process and didn't quite make it through in time for the 10.3.3
release, but in the near future all of our installers will be WiX-based, moving
away from the traditional InstallShield products that we've used for many many
years. In terms of how to get started, just a few pointers if you are
interested in this stuff: a good place to start is wixtoolset.org.
That's the, kind of, open source environment. There's lots of samples, and
the tools you can download from there, and so on. There is a really good
tutorial that is pretty extensive on Fire Giant's website, and there's all
kinds of reference materials out there. There's a couple of recommended books on
the subject as well, so it's pretty easy to get up and running with. I just pretty
much worked my way through the tutorial and looked at other information and
samples that are available, either on the wixtoolset.org site, or Fire Giant site, and
it was pretty easy to get up and running with. Once you install the tool set, you
do get some tooling in Visual Studio, so you get a new folder in the "New
Project" dialog, I think it's titled "Windows installer XML" and within there,
plugs into each language. So it - under C#, you get a folder with with these
projects and the same for VB, and so - uh, no, I guess I'm wrong, sorry. There is a
folder as you can see. So basically a setup project is the main type of
project that you'll use but you can also create the other kinds of things that
are common in the MSI world, so a merge module is kind of a part of a product or
something that you're shipping and maybe embedding in
other projects. You can create setup libraries which are kind of shared
components so you can share functionality between multiple
installations, same as you would use a class library and reference it in other
projects. A bootstrapper project can be used to to create a setup.exe experience
if you wish, rather than just the plain MSI experience and then there are
various custom action projects. Custom actions - a way that you can extend the
functionality of the standard MS windows installer environment and write custom
code that executes during an installation or an uninstall or repair,
and you can write those as you can see in C#, VB, C++, and we have added a
Synergy .NET custom action template to our project templates as well, so you can
also write them in Synergy. Obviously, you have to be a little bit careful with
that, because if you do that, then you have to ensure that Synergy is installed before you try and install the product that uses the Synergy .NET
custom actions. The hierarchy of an installation: basically everything starts
with a product and you'll see that product is the kind of the main element
in the in the XML file, and below products are features. Every installation
will have at least one feature, but could have multiple features representing
required and optional components within a product set perhaps. A feature might be
the documentation, might be sample files that kind of thing.
They can also be hierarchical so you can have features within features and so on,
and they get presented in the install dialog in that tree that we've all seen
from time to time. Below features are components. Components
are used to define things that are installed together as a group, so maybe a
file and a shortcut to the file would probably - possibly be in the same
component, and below that you have things like files, registry entries, environment
variables, and all of the other things that can be part of a product. So I'll
fly through these fairly quickly because I've already spoken to some of these now,
so components are really the main building block of an installation. A
component is all of the individual pieces that go together in
some combination to make up a product. So components contain resources, files,
registry keys, and so on. A component should only contain things that
logically go together. So a file and a shortcut to it would be
a reasonable example of two things that you might put together in the same
component. Every component has an identifier that's used to refer to it
and is identified uniquely globally through a GUID.
So as you're building up this XML you'll be using the GUID generator tool to
generate unique GUIDs for every component, every file, every feature - all of the main entities within an installation have a GUID that uniquely
identifies them not just within the installation, but on the target system as
well. So this GUID is globally unique and it can be used on some Windows system to
say "is this particular component part of this product present on this system?" So
it's important that they are unique and you never - if you copy and paste XML code,
it's really critical that you refresh all the GUIDs and assign new values to
them. Component groups are ways of simply grouping components together. So within a
feature, maybe there's ten files that you want that you go into ship together or
not, so it will be a reasonable thing to put each file in its own
component and then collect them together in a component group, and that component
group could be declared as part of a feature, for example. How you organize
this, there's lots of different ways of organizing this stuff. You'll figure it
out and you'll get - first, you sort of throw everything together but as
you work more in this environment you kind of get a feel for the best way to
achieve things. And then you define features. Features are user-selectable
things within the installation, assuming the user interface allows the dialog or
shows the dialog that allows the user to pick features. So features: generally the
idea is it's something that maybe - some features that can be declared as
required, some are optional and the user gets to pick, and you can default
them either way and so on. And features contain components, and component groups,
and so on. So all installs have at least one feature. Fragments. Fragments is a
syntax in the in the WiX XML language that basically allows you to just
compartmentalize useful pieces of code. A fragment just simply delimits
other pieces of WiX code, and they are used to, for example, split things out
into separate files. So it may be you've got a piece of WiX XML that you want to use in different installations, maybe it does
a particular thing, maybe it's going to be in a WiX library and you just want to
separate that piece of source code out into a separate file just for
maintainability, then you would put that code in what's called a fragment. Okay.
And fragments typically go in source files. There are include files and .wxi is an include file, it's another way of sharing information between multiple
installations or different places in an installation and also set up libraries
if you have multiple installs. I've already mentioned this kind of thing but
a lot of these elements have GUIDs and IDs - the ID is the name by which you
refer to something somewhere else in the in the XML. The GUID is, again,
globally unique worldwide and that identifies specifically that particular -
well, mainly components - but there are some other things that that GUIDs get
assigned to. There are various tools to let you generate GUIDs that are online
tools to let you generate GUIDs. Visual Studio has a little GUID generator
utility that you can use, you can write a program to do it, there's a guid.newGuid will produce a GUID for you. So it's - but it is critical, like I say, if you're copying and pasting, I think in any samples I've produced I
always take the GUIDs and put, you know, "put GUID here" kind of thing so
you can't accidentally reuse them. That's fairly common on the Fire Giant
sites as well. The default setup project when you create one basically looks like
this. It's very, very simple. As you can see, the root element of the document
says WiX and declares a namespace and within that there is a product
tag that defines the product, and the product defines the name of the product,
the version number, the manufacturer. You'll notice that there is an upgrade
code GUID in there. I'm not sure why they generate that into a new project, I
would have thought they would have left it blank, but one of the things you
should probably do is immediately replace that GUID when you create a
new project. I'm assuming it's generate - haven't
actually checked - I assume it's generated on the fly.
But you can see you just do some basic configuration here to name the
product and name the manufacturer, set the version
that you want to use, and so on. And we've got a default fragment here that's
declaring a hierarchy of locations, so TARGETDIR ProgramFilesFolder is a
special keyword - special variable in WiX that refers to the Program Files folder
on the system, and within that we're naming something called "INSTALLFOLDER"
that has a name of "SetupProject1," so we're going to put - we're gonna target
files to go in an install folder and they'll go in Program Files x86 "SetupProject1." So we can name this probably after our company and our product name
and that kind of stuff. So you'll see how we start to customize things. And then
we've got a default - oops - we've got a default fragment with a component and
some comments saying, "start to insert your components here." And here we got a
feature called "ProductFeature" with a title. Level one is the hierarchy in that
tree of features and it references component group "ProductComponents," which
is this guy. So basically any components that we put in here - files, shortcuts, that
kind of stuff, become part of this default feature and part of the
installation. Okay. Configuring new installation. So
initially you're going to pretty much go through the same steps to configure that
default XML file. You're going to provide the manufacturer and product names, set
the version number to whatever you want it to do, if it, want it
to be, if there's an existing product, and specify unique product code
and upgrade code GUIDs. Those are those two things that you saw here, so I
would recommend you replace this one with one of your own. Product ID asterisk
makes it generate a new going every each time it's built. Again, I like to not
do that, I tend to generate a GUID and put it into that Product ID field as
well. So you have a product ID GUID and an upgrade code GUID.
Okay. The product ID - I think actually I'll talk about those in a
little while, so we will come back to that. Frequently you'll also do some work
on the media token that's in that default file. That basically determines
what gets created and how. Is it an MSI file, is it big enough to go on 1.4
megabyte floppy disks or a 650 megabytes CD, or does it just create one huge file
as big as it needs to be. There's all kinds of options for, does it break it
into files that have a 50 megabytes maximum and then it creates another one and
another one, there's all kinds of options for how you want to actually create
the media. By default if you just add 'EmbedCab=yes," the cab file in
Windows installation is like a zip file it contains all the actual files and
then there's the MSI. If you say "EmbedCab=yes," it builds the cab with
all the files and puts it inside the MSI file. So by doing that, that and only
that, you just wind up with an MSI that is the installation. So that's what -
that's the starting point a lot of people go with. And customizing the
target location. By default it has a product name. Most of us put, uh, program
files, than a company name than a product name. So here's an example of that. We've
customized it, we've said manufacturer is Synergex, name is Sample Application.
We've provided product ID and upgrade code GUIDs. The product ID
GUID basically is used to identify a specific version of a product. And the
product ID value should change every time you do another release. Ok. The
upgrade code is used to chain multiple versions together. So for a given product
the upgrade code GUID should never change. It should always be the
same for that product and you change the product ID GUID between versions. And
that's what allows Windows installer to realize that this is an upgrade to that
one so uninstall that one and reinstall this one. They get hooked together
through that upgrade code GUID. And it's not just the GUID actually, it's
the GUI that compares version - you know - the version number has to be logically
higher and there's a couple of other things involved as well to do an upgrade.
Customizing the target install location: the default behavior is on the top left
there, basically ProgramFilesFolder, Set up project one, that gets populated
with the name of whatever project you create and a very common thing to do is
something like the one here, where we've said, below ProgramFilesFolder bind.property.manufacturer is a way of doing data binding to the value of the
manufacturer field in the product definition higher up in the XML file. So
whatever you've set your product name to be,
accompanying manufacturer name and then below it bind property product name, so
you wind up with Program Files x86, Synergex, Sample Application. So that's
an example of how to do that. Installing files: here's an example of
installing a file, you simply define a component somewhere for the file. The ID
is a some kind of unique reference. The way that WiX works is, you put the setup
project in the Visual Studio solution with your product and you reference the
product projects that make up the product, and this this syntax here: var.SampleApp.TargetFileName is a reference to the target binary that is
produced by the Sample App project in the solution. So it's the .exe for the
project, or the dll for the project that you've referenced. You can also just name
physical file specs and things like that. So this is generating an ID and this is
actually referring to the target file itself. KeyPath equals yes. Every
component has to be - has to have one item that is defined as the KeyPath, and what
that means is during things like repair and uninstall it is - in this case it
is this file because KeyPath is set to yes,
therefore Windows installer will look for the presence of that file on the
target system to decide if this component has been installed or not. Okay.
So if you've got a component with multiple files in it, one of them says
KeyPath equals yes and that's what Windows installer will look for the
presence of that file when it's doing to say, "Is this component installed on the
system?" For that reason, there's a general recommendation as far as I can tell, that
pretty much good practice is considered to be to have basically one file per
component. So that - because for repair purposes, if you've got a component
that's got multiple files and one of them is the KeyPath, if that file is the
one that happens to have got deleted that you're trying to fix with a repair,
it can't figure it out because the KeyPath file itself has gone. So by
making every component contain one file, which is also the KeyPath, a possible
repair can detect literally at the minutest level files that may or may
not be missing and put them back in a repair or know to take them away in an
uninstall. So a best practice is one component -
one file per component. You can also, if you're shipping .NET executables -
and you could ship traditional Synergy with this stuff as well it
doesn't have to be .NET, you could ship DBRs and ELBs and all that kind of
stuff - but if you are shipping .NET components, another thing that's
fairly common is to use the NGEN utility to precompile the IL to native code during
the installation so that it doesn't have to be JIT compiled when the application
gets run every time. So at the bottom there you can see the example. You
actually include an X - you reference one of the WiX extensions called net - WiXNetFxExtension. There's a namespace that you have to import at the top of
the file and then within a file declaration you use this NetFx NativeImage, and basically what that does is it instructs Windows installer to NGEN that
assembly after it's been copied to the target location. For better startup
performance. So I'm going to demonstrate to you very briefly a sample
installation. I've got three, I was going to actually build this installation on
the fly during the demo but unfortunately one of the things WiX do
not support in their XML editor is they don't let you do snippets. So I was
hoping to be able to actually build this thing on the fly but we'll have to just
go with pre-configured ones. So here's an example of a very simple installation.
It's a simple demo app. The app is in the project, it's called sample app. It's just
a little Synergy .NET WPF application. If I run it, it doesn't really do anything
particularly interesting. It has some menus, it has an icon, it has, "show the
value of DAT and EXE," which aren't set right now but later after the installs
run they will be. It has a help file that is available, so we're shipping a help
file and launching it, and it has an "about" box which displays information
about the user and the company which is going to be entered through custom UI in
the installation later in the process. So it's looking in the registry and
right now it's not finding it because we haven't run the installer yet. That's all
the application does. It's made up of an executable and a class library, and then
the third project here is the setup project. So we've got a
WPF application, we've got class library, and we've got the installation, and
here's the product.wxs. And in this first version, basically it's not doing an
awful lot. You can see we've said, "EmbedCab equals yes." I've set the product name
and the the GUID values and so on. I've said, "EmbedCab equals yes," so all we
expect to get out of this thing is a single MSI file. We've got a single
feature called product components and if we look down here we'll see Fragment,
ProductGroup, IDs, ProductComponents, and within there we've got two files
being shipped. We've got references - if I look in the
setup project, you see I've got references to the app and the class
library, so I'm using those references to refer to the EXE and the DLL, and both of
them are being NGEN'd during the installation, basically. So that component group lists the components which in turn contains the
files and is referred to from the feature, so when we run the install those
two files will be provided, basically. I've also got a separate installer file
that I've added and in there I've got a little fragment, and the fragment
contains a component group called "DocumentationComponents" and ships the
"HelpFile." So SampleApp.chm is the help file that's actually part of the Sample
App project up here somewhere, I think it is, yeah. So there's the help file that's
been developed in the project. So that's a reference to that and then back in the
main product we've got a second feature declaration: DocumentationFeature, and it
ships anything in the documentation components fragment. Ok. And then back
in the - somewhere up here, where are we? No, that's it, yeah. Two features declared
within the main product element, so we'll get those two features. We've also
modified the target location, so it's going to go to Synergex Sample
Application under Program Files and that's pretty much it, that's all this
install does. When we build the installation project, WiX has two
utilities: one's WiX Candle - one's called Candle, and one's called Light.
WiX...the Candle...Candle is the compiler. It creates an intermediate file,
it's kind of like a IL and then a binary, so Candle is the compiler, WiX is that -
Light is the linker, basically, and it just drives them for us, so you can see
it's done a Candle, it's done a Light, and if we go off to the file system and - I
should have done this earlier so I know where it is...where are we - WiX, Sample App,
demo one, app set up, bin release, because I'm in release mode in the project, so in
bin release, SampleAppSetup.msi. There's our installation. And if we run the
installation, it should provide those files for us. Now, we haven't got any
shortcuts yet, so you know, we're not going to expect - it's done, ok.
Default UI is basically nothing. Ok. So it's done, it's installed, so if we go off
and look in C/program files/x86, we should have Synergex/SampleApplication.
There's the EXE, the DLL, and the help file. And it should, in theory, run and be
able to launch its help file at this point. But we don't have any shortcuts or
anything like that yet. Ok. I'm going to - why did I close that? I'm not going to
run through this process all the time because I'm going to run out of time if
I do, but let me just go back one time and uninstall that, so WiX, SampleApp,
demo one, setup, bin, release, and we will uninstall. I could have gone to programs
and features, of course, it would show up in the programs and features list, and
now it's been uninstalled again. Ok. Let's move on. Sample UI options. The WiX
toolkit ships with five combinations of UI that you can choose to use in your
application. Minimal basically is, you get a single welcome dialog and a license
screen, and then it just goes off and does the install. Feature tree gives the
user access to that list of features so they can pick them.
Mondo is pretty much everything as a whole series of dialogues. Advanced has
got a bunch of additional options: change the target location, and all that kind of
stuff. These things are shipped built-in and
they're also in XML format so that you can take one of the default and
customize it, which I'll show you an example of how to do that very briefly
as well. Some of them have certain requirements, so you just need to do a
bit of research and figure out - you have to have certain variables in your
installation to provide values for certain fields, and that kind of stuff.
We're going to base ours on feature tree. These are the dialogues that you get
with the feature tree UI: you get a welcome dialogue, a license dialogue, you
get to pick features that you do or don't want to install, you get a
"we're ready to install" dialog, you get a progress dialog, and you get a finished
dialogue. So feature tree is a fairly typical set of dialogues for most
installs. There are other dialogues involved as well on uninstall, and repair,
and all of those kind of things, but these are the dialogues you'll see
during the install. Other UI - yeah, so there's other things, like if you
interrupt it there's a "are you sure you want to cancel?" dialogue, if you
select repair, there's a repair dialog that says, you want to change repair or
remove. So there are a few other things floating around in the background as
well. In terms of customizing the UI, the UI itself is defined with XML, so those -
there are those five XML files that are shipped, you can literally include them
in your project and then start modifying them. And then you simply refer to the
dialogue that you wish to use - you'll see this one it's called - I've named this one -
if I can get my mouse..."CustomUI" and in my main product token I'm saying, "UIRef
ID is CustomUI." So I'm overriding the UI that's being used, that default one that
just very basically shows you nothing, and providing this one. And then I'll
show you an example of - well, this is, in fact, an example of customizing. So within
that XML file, I've declared a new dialogue with controls, and these
controls are text boxes, and radio buttons, and labels, and you know, it's not
that usual set of windows controls that you can build up a little piece of UI to
modify your installation. So this piece of XML defines this little UI where you
get to type in a username and a company name. And through some reserved names, these
things get automatically populated with the Windows registration
information, for example. So there's all kinds of things that you can do with
this. This is a very simple example of customizing the UI. Creating shortcuts:
once you've got files, it's a reasonable thing to want to create shortcuts, so
here we've got an example of a component that contains a shortcut. Again, it has -
it's basically, the shortcut has a name, it has a working directory, (where is the
shortcut going to get created), a description, and again, we're binding to
product name, and a target. So that's the ID of the component that provides the
executable and therefore this shortcut points to that executable. Okay. And then, for shortcuts, generally you have to put a value in the
registry to act as the key path to determine if that shortcut's been
provided or not. That's the recommended path. So this is simply dumping a value
in the registry simply so it can be used as a key path for the component to
determine if the shortcut has been installed on the system. And again, that's
used during repair and uninstall. Updating the registry. Well you just saw
an example of that with the key path, but there's this registry key syntax putting
in the H key local machine (HKLM) tree in the key of "Software/Synergex/SampleApplication," again binding to the values elsewhere in
the XML and then creating a registry value type equals "string," name equals,
value equals, and again, it is the key path for the component. So fairly
straightforward to create shortcuts, to put things in the registry. Demo two
basically just takes the same environment and walks it through a
little bit further with those two things. So let me just show you briefly - probably
not going to run this one because I'm getting very - little bit short on time
and I don't want to go over if I can avoid it, but basically this is the same
installation we had before. A couple of things have changed: I've got this
registry entries file, and within it has a frag - it has a fragment and it has a
component group called "RegistryEntries," and basically what's happening here is,
well, let me show you the other part first. Before we do that, I've got custom
UI. So this was a copy of the WiX UI feature tree XML, and I
renamed it to custom UI. This is all the standard feature tree stuff, and then
I've injected this new dialog called "UserCompanyDlg," and these
controls are just labels, and text boxes, and so on, that present the UI and
buttons. And then it's just plugged into the sequence. So the license agreement dialog, which is the previous dialog in the sequence has
had its - where is it - it's next button now goes to "UserCompanyDlg," and UserCompanyDlg's next button goes to what was the next UI in the sequence. So
you just chain the things together in the order in which you want them to
appear. So we've got custom UI, back in our product, we've plugged that UI in. "UIRef Id" is "CustomUI." So that's now the UI we're going to see. The UI has a
license screen and it requires you to have a variable called "WixUILicenseRtf," which points to an RTF file that contains the text for the license screen.
So we've plugged that in there. That custom UI puts the user name and company
name that are entered into two variables called "USERNAME" and "COMPANYNAME," so declaring these properties lets me get a handle on those values that are
entered back in my main installation so I can do something with them. And what
I'm doing with them is in registry entries, here's some code that puts four
things in the registry, so I'm recording in the registry so that it's available
to the application, the username that was entered, the company name that was
entered, the location where the application was installed, and the
version of the product that's installed. Okay. And then that gets plugged into the
main installation. If we look back up here, we've got feature "ProductFeature"
now includes a reference to the RegistryEntries group, so it all hangs together
that way. And that's pretty much what changed in here. Okay.
I'll not run this one - I'll run the final one and show you what the final version
looks like in a few minutes time. But hopefully - does this make
sense? You see how you sort of incrementally build up the installation
just by adding files, and registry entries, and so on. Standard actions. There
are a whole bunch of what are called "standard actions," and these are
like pieces of functionality that you can declare somewhere in your hierarchy. For example there's an element called "InstallExecuteSequence" where you can declare actions that take place and what order
they take place in, and do they take place on an install, or an uninstall, or a
repair, and stuff like that. And the examples of standard actions are things
like, to install Windows - there's an action that installs a Windows service, there's
an action that starts a Windows service, register new fonts into the Windows
system, force a reboot to happen during the - after the installation, all
those kind of things where you want to make something happen on the system.
There are standard actions to support those kind of activities that
installations commonly need to do. And you can also declare custom actions. So a
custom action is a piece of code - custom code - that you want to write to make
something happen during the installation. You can write custom code in several
ways: you can write them in native code, in C++, you can write them in managed
code, in Synergy, in C#, in VB. I think you can also write them in PowerShell as well, PowerScript. So there is a Synergy custom actions template that
we've added into our installation and basically you just have a static method,
you attribute it as custom action, as you can see here in the code. There's a
certain signature it passes in a session object that has various information
about the installation, and you can use it to get our installer variables, or
what's the location of the install, and all that kind of stuff. And you can see
these examples: EditSynergyIni is an example of something you might want
to do during an install, CreateIsamFiles, DeleteIsamFiles. The final
example I'll show you has these as examples with some code built-in as well.
So I've just I've shipped a Synergy INI file that has some placeholders in
there because I don't necessarily know where the data folder is going to be on
the system until install time, so I have a custom action that edits that file
with the install location during the installation because it might not be the
C drive, it could be a D drive or E drive depending on the system, you know, so you
have to do that kind of thing. And I've got an example custom action that
creates a data folder in a public writable folder and puts a bunch
of ISAM files in there and an uninstall action that removes
those ISAM files again during the uninstall. Once you've written the custom
actions you declare them, so basically this "binary ID equals" is basically
declaring when you build a custom actions DLL, it gets this weird .CA.dll
extension, and this is declaring a reference to that DLL and saying
this assembly contains custom actions, and then you declare with a custom
action token each of the custom actions that you want to execute and give it what's called a binary key, and then, basically, you modify
the, again, the InstallExecuteSequence token to say what runs and when. So here
we're saying, we're referring to the EditSynergyIni after InstallFinalize, which is pretty close to the end of the installation. Not "Remove
equals All," which believe it or not is how you say, "only during install," because
it's not "remove all." CreateIsamFiles - run this during installation, and then
DeleteIsamFiles runs before InstallFinalize "Remove equals All." So only during
uninstall. Okay. Setting environment variables is another thing we might
typically want to do. So here's an example of how to do that: Environment Id
equals the ID just referred - lets you refer to it elsewhere, "Action" is "set,"
"Part" is "All" - we're setting the whole value, you can also prepend or our append
information to an existing environment variable like path, for example. The name
of the environment variable, the value - is it system-wide or user-wide, and is it
permanent, so if you say "Permanent equals yes," it will remain after an
uninstall. Okay. So, pretty straightforward. Also a common thing that installers like
to do, or should do, is check prerequisites. This is just an example of
how to check if the .NET framework - actually, this will check if 4.5.2 is there, specifically. The 4.5.2 is based on this number here, this 379893 is - I think it's the build number for
.NET framework 4.5.2 or something like that, there's a
documented list of them. So this just checks if it's there, it doesn't do
anything - all it does if not is, it will report
the error and terminate the installation. There are also ways that you can chain
on and go download it and install it, and then carry on with your install, and
stuff like that. But this is a simple example of just checking a typical
prerequisite. There's another example of how you might go about saying, "is
Synergy installed?" Again, all this is doing is doing a registry search looking
for the SOFTWARE/Synergex/Install...we put a value in the registry SDELOC when we
install Synergy, so this snippet of code is just checking that that SDELOC
value exists in the registry. Not - it could be smarter, I'm not checking
versions or anything like that, I'm just saying, "is Synergy installed?" But
it's a simple example. Also, another thing that's nice to do is, in programs and
features, when your program shows up, there are various hyperlinks that you
can choose to provide at the bottom of the screen that lets the
the user know, "Where do I go for support? Where do I go to check new versions?" So this little snippet of code in the - again, in the main product token,
which would provide values for those things that would just get surfaced in
programs and features, just to make it a nice experience for the user. So let me
just walk you through the final sample. Again, I'm not going to go through the
whole thing in vast detail. I have put the code for all these three examples
out on Github, so there's the URL, or if you just go to Github and search for
Synergex, you'll find me and in my part of the little Github world, you'll find
Synergy WiX example that has all of these three solutions in there. So let's
just look - just so that you've seen the final solution, we'll go for the third
one, which is this guy. So what's happened here is, we've got our custom UI still,
we've looked at registry entries. We've got some custom actions, so SetupCustomActions, here's my Synergy .NET custom actions, one called EditSynergyIni that
just gets a handle on the location using DataFolder, that's one of the IDs in
that location hierarchy back in the product node. And it goes and searches
for ***INSTALLFOLDER and replaces it with the actual install
folder, for example. So these are just public static methods that basically are
attributed as custom action and then they get plugged into the installation,
I've put it in a separate fragment so custom actions, and declare the reference
to the assembly that contains the custom actions, and name the three custom
actions. And then in product, what we will find is that in our execute sequence -
you saw this on the slide earlier, in fact - so called during installation, edit
the Synergy.Ini and then create ISAM files, and during uninstall,
delete ISAM files. So just plugging in the custom actions. You can see we've got
our checks for the framework, we've got our checks for Synergy version, we've got
our informational URLs. I didn't show you this part earlier when we created the
shortcuts, but as well as INSTALLFOLDER under ProgramFiles/Synergex, I've got
ProgramMenuFolder. So that gets you the location of the Start menu, and then
below there I created a sample application folder in the Start menu and
that's where the shortcut gets created. Okay. Other than that, you've pretty much
seen most of this stuff, I think there's the stuff that's putting the values in
the registry. Let's build it and run it just so that you can see it happening. So
let's build the setup program. We are in release mode, so it's going to get
created over in demo three, setup, bin, release, there's the MSI that we - we're
still writing it - there we go, it's finished, and if we install it, we should
see the full experience. This is going to be pretty similar to the CodeGen
installer at this point, so there's our welcome screen, there's our license
screen with our custom UI that we provided - custom text that we provided
through that RTF file. We have to accept that before we move on. Here's our custom
UI that we implemented, the user registration stuff. Let's just put a
custom value in there, just so you can see it running. There's our two features
sample - the sample application is a required feature, documentation, if I
don't want it I can turn it off. And then we should get our ready to install,
there's our progress dialog as it goes through, and now we're finished and we're
installed. So now we should, in our Start menu, find...if we go to the S area, we
should find Sample Application. We've got a shortcut to the app, we've got a
shortcut to the documentation, and actually I didn't show you
this earlier, but I will: it also adds an uninstall shortcut as well. As well as
showing up in programs and features. And if we run the app, we should be able to,
for example, go to our About screen which looks in the registry for those values,
and there's that custom company name that our installer put into the registry after I typed it into the custom UI. Okay. All right. Let's leave it
at that. Let's do an uninstall this way again, just to leave it clean. And
just a couple of wrap-up slides. Back here...Just one more point that if you're
building installations, really you need to digitally sign them as well. If you do
not - if you build an MSI and just ship it out to customers, they're going to get a
pretty scary experience when they try and install that MSI. You won't see it on
your own machine because it gets - if you don't sign it with a real
certificate, it gets signed with a temporarily generated certificate, and
it'll look perfectly normal on your own machine, but if you run it on another
machine...And Microsoft have been making this experience a little bit
scarier and scarier for the last few versions. Now, it's really not that
obvious how you proceed.There used to be a big "okay, install it anywhere" button,
but now you have to drill down into more info, and next, and it says install anywhere.
So they've really done it - they're really trying to hide it away and encourage
users not to run these installations. So the way you get around this is, you buy a
real Microsoft authentic code, code-signing certificate from
Verisign or Thought, or one of those registers or recognized certification
authorities. Yes, that's going to cost you two or three hundred dollars a year, but
it's important that you have one of those and sign the MSI file with it
after you've created it. In fact, my build, not this one, but my CodeGen build, I
just automated that through a process and it runs as a post-build task, every
time I build, the MSI just gets signed. But it's an important step. So the
recommended reading for this session is Copying and Pasting from Stack Overflow.
Yeah, while copying and pasting from the wixtoolset.org, definitely I can
recommend, it's got some great samples out there and the tutorial does take a
little bit of working through, it's like 70 or 80 pages, but it is pretty
good. And of course Blaming the User. One of the best reads out there.
Absolutely highly recommended. Any questions about using the WiX toolset?
Yes, Ace. Ace: We use WiX pretty heavily and one thing that I didn't see you cover
and we're kind of interested in, is how to do MSI patching, because that seems to
be a pretty common thing for us. And I guess my second question to you would be,
you guys ship a lot of hot fixes, when are you going to start giving me MSI
patches? I don't have to run it in a zip file. Steve: Unfortunately, I'm not going to be
able to answer any - either of those two questions. It's something that has been
in the back of my mind to look into as well and I haven't yet. I'm kind of a
novice at this as well, I just learned what I need to learn so far. But you're
right, you can build patches, and you can build merge modules that can get shipped
with other products and embedded, and all of that kind of stuff. And I'll be honest,
I haven't even gone there yet. Marty's the WiX guy at Synergex. Marty: Yeah, I was just going to say, as for shipping MSI patches, the reason we don't is, it would add a lot more
testing. We can currently run a full install through a full QA cycle in a
reasonable amount of time, so it's more - we're more confident in the product if
we just ship the complete installer. Steve: Okay. Audience: Just going back to the merge modules how do we do a silent install to embed Synergex - the Synergy into our installer
or is that not going to be best practice. Steve: That is how you do a site - that is
something that our stuff does support and I'll be honest, I've never
done it, but it's MSI exec - slash whatever it is to suppress the UI. It is supported, you can do it. Okay. Thank you guys. Nigel: Thank you, Steve.