[wix-devs] Running WiX on Linux using Mono

Simon Tatham anakin at pobox.com
Sat Jul 8 01:18:43 PDT 2017

<rob at firegiant.com (Rob Mensching)> wrote:
> This isn't something we'll consider for WiX v3.x (WiX v3.x line is
> done) but there are big enough changes in WiX v4 that we can try to
> make life easier.

Thanks for the point-by-point breakdown.

Sorry for the delay in replying - I've just finished actually getting
the PuTTY 0.70 release out of the door. (Which has its MSI files built
by my Linux-only method, incidentally, if you or anyone else has any
interest in looking at them in detail.)

> 1. ::MsiGetFileVersion() - [...] if it can be shown that the C#
> FileVersionInfo class is a perfect replacement for
> ::MsiGetFileVersion() then I'd consider that like for like swap. I'm
> assuming that Mono (or whatever) has an implementation for
> FileVersionInfo.

I hadn't even found C#'s FileVersionInfo class, so thanks for the
pointer there.

A quick check in Mono confirms that it does indeed have an
implementation of that, and it's at the very least competent to retrieve
the same numeric PE VERSIONINFO fields that my own current Linux support
code is fetching. So to start with I wish I'd known about that facility
before I spent 200 lines of C writing my own custom code to do the same
job :-)

I don't know exactly what you'd consider proof that the replacement is
perfect, but I can certainly look into preparing some weird kinds of PE
file (with multiple, malformatted or missing version resources, that
sort of thing) and do some cross-testing on Windows between
MsiGetFileVersion and (the proper Windows implementation of) C#

> 3. Cab compression in C# - I'm not at all interested at recreating
> "smart cabbing" in C#. However, I am very much thinking about getting
> rid of the multi-threading and winterop.dll and instead launching a
> process to do cab compression. Essentially, much of winterop.dll turns
> into one (or more) executable(s). If you've recreated winterop.dll
> already, not sure this helps significantly... but maybe.

It may not help 'significantly' in the sense of reducing the amount of
code I have to maintain in addition to the main WiX tree, but it would
still help somewhat, so if you were planning to do it anyway then that's

Having a process boundary in place of a DLL API between WiX and my
winterop reimplementation would make testing easier on my side. Also, if
the semantics of the subprocess's command line / standard input are
documented as stable - unlike the current interface to winterop.dll,
which as I understand it is internal to the WiX codebase and subject in
principle to change without notice - then that cuts down my risk of
maintenance churn just to keep the same code working against future

> 4. Stopping at .idt files - unfortunately, with Merge Modules there
> are phases of processing that happen after .idt file generation (WiX
> actually uses .idt files to create the MSI today). You are probably
> avoiding use of Merge Modules today.

*nods* You're right that I hadn't spotted that feature bceause I'm not
personally using it.

OK, so between that and point #3 it sounds as if I'm not going to be
able to offload _all_ my work into the upstream WiX C# code, and will
have to continue maintaining some sort of separate supporting project
for people wanting to cross-run WiX in my way. That's fair enough (it
always seemed to me like a strong possibility anyway). But if the .cab
and .msi building functionality were to move from .dll into .exe, then
that would seem like a pretty good outcome for me, and provide a
generally sensible and well-defined place at which to draw a line
between the two projects.

> So how much of the above would actually help you? Are there are other
> tasks needed?

There is one other thing, which is that my WiX shim code also had to
implement .cab _extraction_ as well as .cab creation, and the only thing
I've actually seen that used for is extracting things from
.cab-formatted files in the WiX distribution archive itself. For
example, in the PuTTY MSI build, I find that WiX asks my winterop.dll to
extract a file called "cab_1_WixUtilExtension.cab", which as far as I
can see comes from data embeddded in WixUtilExtension.dll in the WiX
binary distribution.

.cab extraction is actually a much more painful job than .cab creation.
(For the usual reason when a file format has many options - a producer
can choose whatever subset of the options it finds easiest, and commit
to only generating those, but a consumer has to be prepared to handle
them all. In the case of .cab, the relevant options are three different
compression methods, of which one is the completely standard and readily
available Deflate and the other two are both proprietary and more

So if I'm right that WiX's only need for .cab extraction arises from the
files in its own distribution, then one helpful thing would be to
convert those files into a format that's less dependent on helper code
provided by a particular host platform. Would that be a reasonable


import hashlib; print (lambda p,q,g,y,r,s,m: m if (lambda w:(pow(g,int(hashlib.
 sha1(m).hexdigest(),16)*w%q,p)*pow(y,r*w%q,p)%p)%q)(pow(s,q-2,q))==r else "!"
 )(0xb80b5dacabab6145, 0xf70027d345023, 0x7643bc4018957897, 0x11c2e5d9951130c9,
 0xa54d9cbe4e8ab, 0x746c50eaa1910, "Simon Tatham <anakin at pobox.com>")

More information about the wix-devs mailing list