Well, I managed to figure out the manifest vs SxS problem, at least
enough to make good progress. This message is partly to record what
I've learned, and partly to suggest possible changes to manifest
generation, plus some things I noticed in the documentation and usage.
In summary:
* I'm building my application as a one-file executable.
* PyInstaller generates a manifest file that contains 3 dependency
elements: for Microsoft.VC90.CRT, Microsoft.Windows.Common-Controls,
and Microsoft.VC90.MFC.
* On some machines that I install the executable+manifest on, there's
no SxS folder for Microsoft.VC90.MFC. Thus, on those machines, you
get an error dialog when trying to execute; this is due to the MFC
dependency in the manifest. (I found that out by experimentation;
on such a machine, I edited out this dependency, and the program ran
with no problem.)
* I also experimented with editing out the Microsoft.VC90.CRT
dependency -- this caused the same error dialog; not sure why, and I
haven't pursued it.
So, I added code at the end of the .spec file to read the
PyInstaller-generated manifest from the build folder (using the
ElementTree package), remove the MFC dependency, and write the result to
the dist folder, so it can be distributed with the exe. This now runs on
all the machines I've tried.
Something I learned from some web searches: similar problems occur in
C++/C# development as well; getting the manifest right can be tricky, in
large part because of revisions in the tools and libraries.
I'm not completely sure what to recommend; here's a few possibilities:
* Remove the Microsoft.VC90.MFC dependency from the automatically
generated manifest file.
* Make the contents of the manifest more configurable, so the
developer can tailor it for the intended target machines.
* Check with the Python developers, who might be able to help (I'm
thinking especially of Mark Hammond, who may be the best source for
Windows issues.)
That aside, here's a few things I noticed, especially in the 2.1
documentation:
* In the "Installed commands" section, several commands prefixed with
"py-" are mentioned, but they don't exist.
* COLLECT isn't well described, although several examples are given of
its use. In particular, it would be useful to point out that it's
the presence of COLLECT that marks the difference between a one-file
and one-dir build.
* The pathex argument to ANALYSIS isn't described anywhere.
* There's a variable WORKPATH that's defined when building, and can be
referenced in the .spec file; it points to the build directory.
This can be useful for postprocessing, and should probably be
documented.
* I ran a build with log-level=WARN, and got a few INFO messages.
(Would it be possible to include something in the spec file to
declare a default log level? I can imagine wanting the debug level
during development of a complex spec file, then changing it to warn
or error for production builds.)
Finally, for what it might be worth to someone, here's the code I used
to copy the manifest to the dist/ folder, stripping out the MFC dependency:
# At this point, the manifest file is in the WORKPATH folder; we need
it in the dist folder.
# Also, we need to do some surgery on it to make it usable on machines
that don't have
# the assemblies for the MS MFC dlls. This consists of deleting the
dependency element
# that references the Microsoft.VC90.MFC assembly. The following code
does both.
import xml.etree.ElementTree as ET
tree = ET.parse(os.path.join(WORKPATH,"CCAuthLogBrowser.exe.manifest"))
# Now find the target element to be removed
# The logic here is:
# look in each 'dependency' element for an assemblyIdentity element
(2nd level down)
# whose name attrubute is 'Microsoft.VC90.MFC'
# This should return a one-element list, containing the target to be
deleted
target = [e for e in
tree.iter('{urn:schemas-microsoft-com:asm.v1}dependency')
if
(e.find('*/{urn:schemas-microsoft-com:asm.v1}assemblyIdentity').attrib['name']
== 'Microsoft.VC90.MFC')] [0]
target.clear()
# Write out the edited tree (the extra args are to include "<?xml
version='1.0' encoding='UTF-8'?>")
tree.write(os.path.join('dist','CCAuthLogBrowser.exe.manifest'),
xml_declaration=True, method='xml',
encoding='UTF-8')
Thanks for reading,
--
Don Dwiggins
Advanced Publishing Technology
--
You received this message because you are subscribed to the Google Groups
"PyInstaller" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/pyinstaller.
For more options, visit https://groups.google.com/groups/opt_out.