executables no longer executing on PC's without Python installed

jefm jef.mangelschots at gmail.com
Tue Dec 16 20:21:23 CET 2008


Hi,
I recently figured out a problem that came up with the latest versions
of Python and cx_Freeze. I thought I post it here so that it might be
usefull to someone.

The problem was that, when I switched to Python 2.6.x and
cx_Freeze-4.0.1.win32-py2.6.msi, the executables that were produced
ran perfectly on my PC but not any other PC. They did not print any
useful information whatsoever.

Googling around, I learned that it had to do with Visual Studio being
installed on my PC and not on the other PC's.
The common solution that worked for other people was to put the
redistributable manifest and DLL's from C:\Program Files\Microsoft
Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT,
into the same directory as the generated EXE.

This didn't work for me. With the help of Anthony Tuininga, I finally
tracked it down to the DLL version.

In the good ol' days, when your application was lacking the C rntime
library DLL in its search path, it gave a clear warning.
e.g. "can not find msvcr71.dll" or something like that.
The only thing you needed to do was to go look for one (either on your
PC or on the internet), and pluck whatever DLL with that name into the
search path, typically in the same directory as your exe or windows
\system32.
It didn't care about different versions of DLL's.


Now with the advent of at least Visual Studio 2008 (and probably 2005,
but I skipped that one), Microsoft, in its infinite wisdom, decided
that that method was way too easy for everyone and came up with yet
another way to torment everyone that dares to develop software in
anything else than Microsoft monstrosities.
I am referring to these mysterious things with names like "side by
side installation", "SxS", "manifests", "assemblies", ...

Why does the noble community of enlightened scholars developing Python
care at all ? Because Python 2.6 binaries for Windows are now compiled
using Visual Studio 2008. In essence, that should not mean more than
replacing your msvcr71.dll with msvcr90.dll. Unfortunately, you
inherit this "assemblies" crap with it.

The new terminology invented with this and the MSDN articles on this
subject make it only more obscure and complicated than it should be.
In a nutshell, DLL's now are attributed with a version number.
Executables generated with VS2008 are now restricted to run only with
a predefined specific version of a DLL. This allows you to run
executable A with version X of a DLL and another exe with version Y of
that same DLL and not be affected with obscure bugs caused by pairing
the wrong version of a DLL with an exe (the infamous DLL hell).

How do you pair an exe with a particular DLL version ? That is done
with manifest files, basically a small XML file, listing the exact
version number and some obscure hash numbers for integrity checking. I
haven't figured out how to manually produce these (VS2008 does this
for you) but fortunately for us, Python developers we don't need to
care. We just have to use the same one the Python distribution was
compiled with.

How do I know which version Python is compiled with ?
The easiest way is to install Python with the option "install just for
me". This has the result that the msvcrxx.dll used by Python is copied
into the c:\pythonxx directory instead of in a common windows\system32
folder (or something like that).
This was my first mistake, I used the other option "install for other
users".

This should not be a problem. cx_Freeze is clever enough to go out and
find this DLL for you. It will probably find the right one, PROVIDING
you have the right version of the DLL's in your search path.

Now back to Microsoft. Up until around 9/16/2008, there was only 1
version of msvcr DLL's, nl. 9.0.21022.8 and that was good, because it
happens to be the same version Python was installed with.
The only thing you have to do is to accompany your generated exe with
a manifest with the correct hieroglyphs, copy this dll in the same
directory and you were done.
(you actually need 2 manifest files: one that accompanies to the exe
which DLL version it needs, and another manifest file that specifies
the versions of the DLL. The exe manifest can be embedded in the exe).

Poor old Anthony Tuininga had to figure this out the hard way. He
makes our lives a lot easier by already embedding the correct exe
manifest into the executable. You can check this by opening the
generated binary with a hex editor and scroll down until you see some
XML. That is the manifest. That will tell you which DLL's it needs and
which version (nl. 9.0.21022.8). It needs to be this version because
of the version of Visual Studio 2008 used to compile Python itself.

Having Visual Studio 2008 installed on your PC while freezing your
Python apps should not be a problem. Even if you didn't specify
"install just for me", cx_Freeze will probably find msvcr90.dll
somewhere.

But then came Visual Studio 2008 SP1. With it came an updated
msvcr90.dll with version 9.00.30729.1.
That is what I had installed and things went south from there.

Recent versions of Windows now come with the directory C:\WINDOWS
\WinSxS, in where you find all the versions of these DLL's (this is
what they refer to as "side-by-side installation", i.e. instead of
copying these common dll's in system32 folder, every version is now
copied in a directory with a particular name, containing the version
number and all manifest files copied in C:\WINDOWS\WinSxS\Manifests).

When I installed VS 2008 SP1, it copied a later version (9.00.30729.1)
of msvcr in there "side-by-side" with the original version
(9.0.21022.8) which came from the original VS2008 and which I needed
to get my frozen Python26 exe's to run. For some reason, Windows
couldn't figure out which DLL to choose.

I followed the advise I found on the internet to find the c:\Program
Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT
folder and copy its content (being Microsoft.VC90.CRT.manifest and
msvcr90.dll) into my bin directory. This didn’t work.
Unfortunately, I had already updated my Visual Studio 2008 to SP1 and
this using the wrong version (9.00.30729.1) Had I not updated to SP1,
I would not have had this problem.

Not understanding the problem, it looked like I was forced to have all
my users install the Microsoft Visual C++ 2008 Redistributable Package
before running my tools.

Fortunately, this is not necessary. The solution is very simple:
after having generated your application with cx_Freeze, copy the
following files (and only these files) to your executable directory:

C:\WINDOWS\WinSxS\Manifests\
x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-
ww_d08d0375.manifest

C:\WINDOWS\WinSxS
\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375\
msvcm90.dll
msvcp90.dll
msvcr90.dll

I think this applies to py2exe as well.

If you do not have these files, you can download these from the
following link:
Microsoft Visual C++ 2008 Redistributable Package (x86) (11/29/2007)
http://www.microsoft.com/downloads/details.aspx?familyid=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF&displaylang=en

note:
beware, there is now an SP1 version of this, which caries the
(incorrect) 9.00.30729.1 version.
I am not sure it carties the (correct) 9.0.21022.8 as well. If it
doesn't, you need the other installation.
You can find SP1 from:
Microsoft Visual C++ 2008 SP1 Redistributable Package (x86)
(9/16/2008) http://www.microsoft.com/downloads/details.aspx?familyid=A5C84275-3B97-4AB7-A40D-3802B2AF5FC2&displaylang=en


note: I don't understand why Microsoft doesn't distribute the C
runtime libraries (msvcrxx.dll) with the next Windows Update and
squirt that puppy in every Windows PC on the planet.


Hope this helps.

Jef Mangelschots



More information about the Python-list mailing list