Saturday, March 14, 2015

An easy guide to installing using WIX

This tutorial is for everyone who just wants to build a simple installer using the WIX toolkit to generate a standard .MSI file. The sample has a couple of files; they get installed. A shortcut is added to the desktop. That’s it. You can read my sample, and be done in fifteen minutes, or you can wrestle your way through the maze of arcania that is the official documentation.

The first step is to install WIX; luckily it’s not hard. Go to the site and pick a published stable release. I used v3.9 R2 (stable). The second step is to make a directory, and dump my project files there. I used c:\temp\2015\wix, but you can use anything.

The project files is a dummy EXE, a really dummy DLL (it’s just some text), a dummy license file and a dummy help file.  There is also a .WXS WIX installer file and the BAT file that will generate a .MSI installer file. 

Edit the MyApp.msi file and make the following changes. They are detailed below, but here’s the general rule: everything with ‘myapp’ needs to be changed.

  1. Change all the GUIDs! Search for MYAPP-GUID and replace the guid. Seriously, this is critical. Note that every guid is different. There are three of them.
  2. Once you change the GUIDs, you can try the MakeInstall.bat file to make a .MSI installer file.
  3. Everywhere that there’s a MyApp in CamelCase, the string is visible to the user. This includes:
    • Product Name and manufacturer
    • Package description, comments and manufacturer
    • Property for the disk prompt (I don’t know when this will ever show up)
    • Directory to install to (which is always in the program files directory)
    • Shortcut name (the shortcut is installed on the desktop)
  4. Everywhere there’s a myapp in lowercase, it’s something that isn’t visible to the end-user
    • Media cab file (I don’t know where this is ever used)
    • File name and source for the myapp.exe, myapp.dll and more
    • The icon reference the app name
  5. Everywhere there’s a MYAPP that is all uppercase, it’s an ‘ID’. The WIX idea is that some IDs are actually chosen so that different parts of the system can refer to one another. Other ids are not like that, and have specific requirement (e.g., the icon id MUST end in .exe, which violates every principle of naming things that ever existed.

Run the MakeInstaller.bat file to make a .MSI file. There are two programs that get run, ‘candle’ and ‘light’. The BAT file will also clean up the useless intermediary files.

And like magic, you have a working installer!  Start by just using my files and just update the GUIDs in the MyApp.msi file and generate an MSI.  Then once you have a working installer and a workflow to make it, you can get fancy and install your programs and files into your preferred directories.

All my sample files are in this ZIP file.

Good luck!

Sunday, July 6, 2014

Linear motion with XAML and Storyboard animations!

One of the remarkably cool things with XAML is how easy it is to set up animations.  Most of the time I just need to animate some opacity.  A quick web search, and boom!  I’m in business.

But for some reason, animating motion (like: move my text box off screen) is a pain.  Here are the important steps.

  1. Give your object an x:Name (“obj”).  Let’s also assume that the object is a custom object of type local:JokeControl.  The word local refers to a XML namespace definition.
  2. Add a RenderTransform with a TranslateTransform child to your object
  3. Add in a storyboard and give it an x:Naem
  4. Set the storyboard’s TargetName to the object name
  5. Set the storyboard’s TargetProperty using the weird ‘path’ syntax: (local:JokeControl.RenderTransform).(TranslateTransform.X)

And then in code, just call “.Begin()” on the animation!

Here are the actual bits of code:

From the XAML file:

Notes Code
Set up the ‘local’ namespace so that my user control (which is in C# namespace ‘Jokes’) can be used. xmlns:local="using:Jokes"
Create the animation in the resource section.  The storyboard (animation) is named uiAnimateJokeOut, and actually has more bits than this.

    <Storyboard x:Name="uiAnimateJokeOut" >
            From="0.0" To="400.0" Duration="0:0:0.5"

The object I want to animate needs a RenderTransform; the particular render transform I need is a Translate transform.  I don’t have to name it because I’ll find it by type.

<local:JokeControl x:Name="uiJokeControl" Grid.Column="1" >
        <TranslateTransform X="0" >

C# code to start the animation uiAnimateJokeOut.Begin();

While I’m at it – I wanted the joke control to move right to go off screen, and then come back.  And I wanted to change the joke when it’s off the screen.  I did this by making two animations (one for joke OUT and one for joke IN).  I then added a .Completed on the OUT to swap jokes and to bring the joke back in.

The code looks like this:

uiAnimateJokeOut.Completed += (s, args) => { DoRandom(); uiAnimateJokeIn.Begin(); };

Thursday, June 23, 2011

Multicast -- it's not really hard at all

So, I've been trying to learn some multicast programming. What I really want, of course, is to run a program on one computer in my local network (otherwise known as "home"), and then discover it on another computer.

So I figure multicast is the answer. And, in truth, it is! It's great! It's even simple! But every single silly blog post about it -- especially from the vendors -- makes it sound hard.

Here's the real deal on Multicast. It's just UDP. You send it to an IP address like The exact values are pretty unimportant. And the port is just a port, like 9883. The server (listener) is just a hair more complex: bind to the same port, and set the "multicast join" socket option to the IP address.

Tada! Packets sent by the sender go to the listener. And you can reply from the server back to the sender by looking at the remote IP address.

Monday, December 29, 2008

Issues with LIB files (a riff on Raymond Chen)

Today's The Old New Thing blog talks about a subject near and dear to my heart: why the Microsoft Linker needs some TLC when it comes to making lib files.

Let's back up.  What's a lib file, and why do they exist?  Well, a long time ago, computer programmers decided that the mechanics of converting what a programmer writes into what a computer understands should be done in two steps: a compiler turns the "source file" (what the programmer wrote) into a "object file" (a temporary file).  Then a linker turns the object file into a program.  It turns out that in general compiling is much slower than linking, and that most programs are composed of many source files, and that you don't have to re-compile a source file that hasn't changed.  So if your program consists of a hundred source files, and you change one, you only have to compile one, and then link them all together, and you get a program.

Now the twist come in: with bigger projects, it's handy to lump all of the object files together into a "lib" (library) file.  That way you don't have to tell the linker about all of your files; you just point it to the one lib file.

That's where the Microsoft Linker falls down, badly.  A common pattern for using lib files is to split the people using the lib file from the people who are making it.  As such, I want to pack my lib files with "everything" the user might want to use.  

But you can't.

As Raymond Chen points out in his (much better) blog , The Old New Thing, today (link:, it's eay to compile a file one way, put it into a library, and have a user compiling and linking another way to almost but not quite use your symbol.  It's very frustrating and requires a bit more fixing ability then we should expect end-programmers to have.

There are three things I'd like to see with the linker:
  1. On failure, the linker should try a fuzzy match ("I didn't find 'xyz' but I did see 'xyxz@4')
  2. The linker should keep track of how all of the files are being compiled ('the library was linked with /FOO but you are compiling with /NOTFOO)
  3. A library should be "stuffable" with all of the different versions of a file -- I should be able to pop in the unicode and ansi, debug and release, statically linked and dynamically linked versions of all of my files. 
The goal, of course, is to let me as a library-creator make a library that other people can "just use" -- not "just use with a lot of swearing".

Sunday, December 28, 2008

About Me and Where I Work

Thanks to the local economy, I recently was part of a layoff at a company which I'll simply describe at the "Purple Company".  People who work there will know what I mean.  Luckily I picked up a new job very quickly as (cue ominous music) one of the networking people for Microsoft.

I wouldn't bother mentioning it, but at the NEO (New Employee Orientation -- everything at MSFT has an acronym) it was mentioned -- and repeated -- and then emphasized:

We can write a blog.  MSFT likes us to write blogs.  But the legal staff is worried about looking sneaky, and they'd like all of us MSFT bloggers to mention that we are, indeed, MSFT employees.

So there.  I work at Microsoft.  I won't put in a disclaimer that I don't speak for Microsoft because IMHO that should be the default legal status on the internet.  And you'll see from previous entries that I've been definite about MSFT's poor documentation (and sometimes bizarre code).

Friday, September 26, 2008


So, I'm trying something simple: redirect the output of a command to a file.  For no obvious reason, the utility decided that some of the data was 'stdout' and the rest was 'stderr'.  So all I need to do is the 2>&1 redirect trick, right?

Right.  But it's much stranger than that.

cvs annotate >data.dat 2>&1

is the correct command.  The wrong command is 

cvs annotate 2>&1 >data.dat

See the very subtle difference?  I sure didn't.  Because it didn't work right away, I had to start debugging it -- was it really putting output into those two pipes? (yes).  Can I pipe them each, one at a time? (yes)  Can I google for the correct syntax (yes).  Nowhere did I see the warning: you must do the 2>&1 pipe AFTER the >data.dat redirect.

Interestingly, if you first redirect output 1 (stdout), then pipe output 2 (stderr) into 1, then redirect output 1 to a diferent file, output 2 goes to the console.  I'd expect it to go into one of the two files that 1 was redirected to.  And output 1 eventually goes to the last file it was directed to.

ObLink: Microsoft badly documents the pipe operators at:

Tuesday, September 2, 2008

Dreaded LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs

Perhaps the most irritating misfeature in the Microsoft compiler/linker family is the complete inability to make proper library files. What's a library file, you ask? Simple: it's where one person writes a bunch of code in a nice high-level language and then converts it into a single, neat "lib" file that a second person can then use in their program.

Conceptually, it's a no-brainer. Getting a good implementation of this, though, is beyond Microsoft's ability. It's easy to make a library -- it's just not possible to make a library that an arbitrary other person can use. (I'm currently interfacing a small program to Erlang; they have to ship three different libraries on Window just to get around the issues).

Microsoft keeps on changing their run time, so you have to match versions. They have multi thread and non multithreaded, and using MFC and not using MFC, and link against DLLs and link to a static library, debug and non debug -- there are too many options when what we really want to do is make a single (gigantic) "lib" that other people can use seamlessly.

Case in point: the dreaded LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library message that pops out when you go to use someone else's library. What it means is that some compiler setting that most people don't care about at all is set one way in the library and another way in your own code. Microsoft's advice ('use /NODEFAULTLIB') is useless.

What often works for me is the /VERBOSE:LIB switch (which you have to type in yourself). It lets you see exactly what libraries are being pulled in; from that list you can (generally) tell what has to be updated.