Update of pp
As part of the Visual Studio 2017 upgrade, pp was recompiled. At this time WixApp has been created and it is being used to create the Product.wxs file used by Wix to build an installer. It also uses SetEnv to install a link to the pp.exe in the system Path variable. Both SetEnv and WixApp are discussed else where.
My Library is used with pp but it is not included here. Look for it elsewhere in the site.
I am using Visual Studio 2013 version. I am also using SlickEdit for most of the editting and compiling tasks. So where did I begin this journey. I originally installed (copied) pp to C:\Local\ and manually placed a link in System.Path to "Local". That was probably 4 PCs ago (late 90s). Recently I've embarked on cleaning up several development projects. One of the tasks was to provide an installer for a couple of the projects. Then as these things go I just had to add an installer to all of the projects.
The Print Program (pp) is a command line program out of the dark ages. As described in the Modules page, it has some redeaming capabilities so I've kept it alive all these many years. This last week (October 2017) I wanted to create an installer for it. Visual Studio 2013 doesn't support an installer but by "adding" one to Visual Studio from the Microsoft Toolkit (add link) a Microsoft "approved" (if that is the right adjective) installer is available. The documentation for the installer is very clear: No support for adding a program's path to System.Path. Furthermore there is no way to invoke an external program to do the job for the installer.
Searching for a solution yielded one interesting suggestion: Wix. Wix would allow invoking an external program but everyone agrees that it is a difficult program to understand and use.
Wix is not a procedural language. It more or less is a description of some things that should happen when the Microsoft installer is invoked with the data in the ".msi" file. Wix provides a way to supply the data needed.
My purpose in this little paper is not to document Wix but rather to document those things I learned the hard way. Wix is adequately documented online and in at least one book: " Wix 3.6: A Developer's Guide to Windows Installer XML " by Nick Ramirez published by PACKT. Start on page 1 and construct the example "Amazing ..." in Chapter one and work through the next few chapters adding and modifying the example. This will prove to one that Wix works.
Now I want to document those things in Wix that caused me trouble so that the next time I embark on a Wix adventure I have some help to avoid the issues I discovered this time around. Here is a pdf file of the Product.wxs that produces the installer for pp.
The Wix File must begin with two XML lines.:
<?xml version="1.0" encoding="UTF-8"?>But following those lines at least four different XML statement types can appear:
<?define ...?>One of the issues is that the "include" statement may only appear after the initial two lines and outside of any of the other XML structures. Note that XML requires that the Product tag is closed by a corresponding </Product> and the Fragment tag must be closed by a corresponding </Fragment>. It would have been nice if an include statement could appear between the Product tags.
One of the issues was providing one declaration for the directory in which the files could be found. There is an extensive mechanism for identifying the location where the files should be installed (by files I mean the executable, shortcuts and data files). However all the documentation I've read (which is admittedly not all that much) always use just the file name as if the file is in the same place as the Wix file. The define tag allows one to define a variable which can define the path. In this installer I also need the path to three files which I may use in several places.
<?define SourceDir = "$(var.SolutionDir)\Release\" ?>
<?define WixInclude = "D:\Sources\WixIncludes\"?>
The WixIncludes content may be found here. It is included with the Print Program because it is required there to create an installer.
The Product block is the outer entity of the install package. It includes the following tags:
- User Interface (UI) Declaration and Modification
- Icon Declarations
- External Executable Declarations
- Feature Block
There are four predefined user interfaces. The one chosen, WixUI_InstallDir, allows just one change, the destination directory. However it also requires the user accept a license agreement, you know the one that nobody reads. I searched high and low for a way to skip the license agreement. The UI block changes the control flow from the Welcome Dialog to the InstallDir Dialog.
Windows is an Icon rich interface. The user interface has a standard bit map for both the side of dialog box and a banner about the white area used for text. They have special names and can be replaced. The program may be represented by icons in various places. There are typically two such icons, one for the program and one for the uninstall program. In this instance they are the same as the only program that needs an icon is the uninstall program. The ARPPRODUCTICON is another special name the places the icon mentioned in tag in the Control Panel/Programs and Features (Win 7).
The last interesting section of the Product Block is the Custom Action declaration. In my search for an installer that would add a path to System.Path Wix provided a way to do that. A custom program could receive information directly from the installer during both an install and an uninstall. The programs job would be to add and delete the path from System.Path.
The order of the Custom Action tags is important. I tried two different organizations for the Custom Action declarations. The first was to place the Custom Action declarations in a Fragment. Didn't cause a compile error but the custom action did not run. Oh well. The second organization was to place the Custom Action declarations in an Wix include file (i.e. .wxi) and place the <?include ... ?> just before the Feature block. No joy there either.
The two fragments are just used to separate pieces of the Product. They are discussed at length in the Wix 3.6 book. The Properties ApplicationFolderName, WIXUI_INSTALLDIR and WixAppFolder are used in the UI.
SetEnv is called from the Wix Installer when necessary (and instructed by the user in WixApp).
Searching the internet and the Visual Studio 2013 Help files I found the functions:
- System.Path is empty
- System.Path has one path, i.e. the given path. In this case no semicolon follows the path
- System.Path has two or more paths and the first one is the given path, i.e. the given path is followed by a semicolon
- System.Path has three or more paths and the given path appears between semicolons
- System.Path has two or more paths and the last path is the given path, i.e. it is not followed by a semicolon
The SetEnvPath source is here. (5/5/19) SetEnv is now compiled separately.
Another gotcha occurred recently with the SetEnvPath program. There was a problem with the latest version of WinZip (v22). I was a good citizen and ran a number of experiments for the WinZip folks to see if we could isolate the problem. One of those experiments required me to remove all but the most recent versions of the Net Framework from my system. Unfortunately, SetEnvPath's compilation requires Net Framework 4.6.1 (I believe it is the last version that may be used in Visual Studio 2013 (VS13)).
So I spent a good deal of time trying to get VS13 to accept a later version but that was not to be. I finally reloaded a clean version of the Net Framework 4.6.1 target package and that fixed the problem.
There are at least two places that a shortcut to the executable should appear. One of those places is in the Start Menu in a Folder with a name on it that indicates the product (either a company name or the name of the program). The other place might be the desktop.
Wix provides at least two ways to specify the shortcut. One way is to include the shortcut inside a Fragment and DirectoryRef separated from the actual program declaration. The program reference may be given with a '#' followed by the id of the program. Unfortunately there is another feature of the start menu shortcut, 'Advertise="yes"', that causes a warning when the shortcut is in a Fragment. The Advertise attribute of the shortcut will place program shortcut between the pinned shortcuts and the "All Programs" button. So take a look at the AwesomeProduct.wxs.pdf file to see a solution to the warning, i.e. placing the shortcuts in the same Component as the file to which the shortcut points. In this case instead of being inside of a Directory Reference the shortcut must include a Directory attribute to specify where the shortcut is to go