classification
Title: Specifying common controls DLL in manifest
Type: behavior Stage:
Components: Build, Windows Versions: Python 2.6
process
Status: closed Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: loewis, robind
Priority: normal Keywords:

Created on 2009-01-21 02:00 by robind, last changed 2009-04-27 16:31 by robind. This issue is now closed.

Files
File name Uploaded Description Edit
python.exe.manifest robind, 2009-02-09 21:58 sample manifest that includes the common controls dependency
sample.py robind, 2009-02-09 21:58 simple sample wxPython app
Snap001.png robind, 2009-02-09 21:59 sample running without themes on Vista
Snap002.png robind, 2009-02-09 21:59 sample running with themes on Vista
bindtest.zip loewis, 2009-02-23 11:18
Messages (10)
msg80308 - (view) Author: Robin Dunn (robind) Date: 2009-01-21 02:00
This may have already been discussed but my searches didn't turn up
anything concrete other than issue 4120 which is a similar but different
problem.  The problem I'm facing is that wxPython requires that version
6 of the common controls DLL be loaded in order for the GUI applications
to use the themed version of the widgets on XP+ platforms, but it
appears that this can only be done reliably if the manifest for the .exe
is the one that specifies that version of the common controls assembly.

Prior to 2.6 I was able to install python[w].exe.manifest files next to
the python executables from my installer and it would work fine, but now
that Python 2.6 is built with MSVC9 and it has its own manifest that
does not always work.  Initial testing seems to indicate that using an
external manifest still works ok on 32-bit platforms, but not on the
64-bit versions of Windows.  

I've tried ensuring that the wxPython .pyd's and the wxWidgets DLLs have
an internal manifest that specifies the common controls assembly but
that has not helped.  The only thing I've been able to find that works
for both 32 and 64 bit is to replace the internal manifest in python.exe
with a new one that specifies both the CRT and the Common Controls
assemblies, but that is obviously a Bad Thing for the install of an
extension module to do, so I'm opening this issue to look for alternatives.

So, does anybody have any experience or ideas on how to enable the
wxPython extensions to load the new common controls assembly without
needing to change the stock Python executables' manifest?  If not, are
there any objections to adding the common controls assembly to the stock
manifest used for python.exe and pythonw.exe?
msg80318 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-01-21 06:48
See issue4566. If you explicitly create "activation contexts", you might
be able to have it load the right DLLs.
msg81492 - (view) Author: Robin Dunn (robind) Date: 2009-02-09 21:26
If I understand correctly then setting an activation context won't help
because by the time that an extension module is loaded the choice of
which version of the common controls DLL will be loaded has already been
made, and it may in fact already be loaded.  The system must be told at
the time that the .exe is loaded which common controls DLL it wants,
otherwise it will use the old non-themed version.  Everything I've tried
seems to confirm this, if that is not true I'd love to see some examples.
msg81493 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-02-09 21:32
Can you provide an example of a manifest file, and a Python script, that
demonstrates the problem? I have only heard of themes, never seen them
myself.
msg81504 - (view) Author: Robin Dunn (robind) Date: 2009-02-09 21:58
Ok, the following files will be attached:

python.exe.manifest: This is a copy of the manifest resource that I put
into the 2.6.1 python.exe file by hand for testing.  The original
manifest was the same but without the 2nd <dependency>...</dependency>
group.

sample.py: the simple little sample I used to make the screenshots.

Snap001,png: This is sample.py running with the original python.exe
running on Vista.  Notice the plain, flat, outdated and ugly win2k look
and style of the notebook tabs and buttons.

Snap002.png:  The same sample running with a modified python.exe.  Now
it has textures, gradients, mouse-over effects and etc. and will match
the look of other modern applications running on the machine that are
using the standard themes.
msg81513 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-02-09 22:58
It looks like it should be possible to bind to a different comctl32.dll
than what gets loaded by the host application. See this KB article:

http://support.microsoft.com/default.aspx/kb/830033

which even claims that you should be able to do so with manifests
(notice how you need to define ISOLATION_AWARE_ENABLED to get different
versions of CreateWindowEx etc); also see the .NET code on how they use
explicit activation contexts 

Also see

http://blogs.msdn.com/junfeng/archive/2007/06/26/rt-manifest-resource-and-isolation-aware-enabled.aspx

for an explanation what resources must be defined so that a DLL can bind
to a different version than the rest of the process.

I think you want to put the comctl32 manifest binding into RT_MANIFEST
resource 2 (not 1, as you probably had tried so far).
msg81529 - (view) Author: Robin Dunn (robind) Date: 2009-02-10 04:46
Sorry, no luck.  I've tried before to ensure that all the DLLs and
extension modules have the manifest file (in resource 2) and it makes no
difference.  I rebuilt wxWidgets and wxPython today with
ISOLATION_AWARE_ENABLED defined to check if that would help, and reset
the manifest resource in all the binaries, but it makes no difference.
msg82623 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-02-23 11:18
Here is a demo of how to make a nested DLL bind to comctl32 v6, even if
the main application binds to a different version of comctl. The DLL has
a ISOLATIONAWARE_MANIFEST_RESOURCE_ID resource.

To see what happens, run Release\bindtest.exe, and invoke File/test.
Watch the message box, and the dialog created from within the DLL. For
comparison, rename the manifest.0 to .manifest, and watch the message
box also change its button style. Tested on XP.

The sources are built with VS2008. To simplify the experiment, both the
main application and the DLL links msvcrt statically.
msg82945 - (view) Author: Robin Dunn (robind) Date: 2009-02-28 19:46
Thanks for the code.  I've verified your findings and I've also
converted nested to an extension module and built it with distutils and
was still able to make it correctly load the themed common controls when
imported from Python, however I had to hack distutils a little bit to
keep it working.  In this case the code in msvc9compiler.py that runs
mt.exe overwrites the manifest that is specified in the rc file with one
that doesn't include the common controls assembly. 

I've still got to figure out what is the difference between this test
and wxPython's build...  It seems that none of the obvious things have
any effect.
msg86675 - (view) Author: Robin Dunn (robind) Date: 2009-04-27 16:30
Update:  I finally worked out what needed to be done for wxPython and
while simply changing Python's manifest would have been immensely easier
what I have does seem to work well so I thought I should give some info
here for posterity.

I went back and experimented again with creating an Activation Context
in the C code that loads a proper manifest, and found that it seemed to
work in some situations and not in others.  I eventually narrowed it
down to the fact that any UI object created from within a timer event
handler would always use the processes' default context instead of any
other activated context.  (In this case that means that it would always
use the manifest embedded in python.exe instead of any other manifest,
programatically loaded or otherwise.)  Since the main frame in
wxPython's demo is loaded via a timer (when the splash screen times out)
then this made it appear that all of my prior experiments had failed,
when in fact some of them probably at least partially succeeded.

After further experimentation I found that switching wxTimer to use a
hidden window for catching and processing timer events, instead of using
a TimerProc callback, solves the problem with the new activation context
being ignored.  So I guess we can call this a microsoft bug and move on.

More details are in this thread:
http://lists.wxwidgets.org/pipermail/wxpython-dev/2009-April/004199.html
History
Date User Action Args
2009-04-27 16:31:00robindsetstatus: open -> closed

messages: + msg86675
2009-02-28 19:46:12robindsetmessages: + msg82945
2009-02-23 11:18:20loewissetfiles: + bindtest.zip
messages: + msg82623
2009-02-10 04:46:31robindsetmessages: + msg81529
2009-02-09 22:58:11loewissetmessages: + msg81513
2009-02-09 21:59:52robindsetfiles: + Snap002.png
2009-02-09 21:59:34robindsetfiles: + Snap001.png
2009-02-09 21:58:58robindsetfiles: + sample.py
2009-02-09 21:58:39robindsetfiles: + python.exe.manifest
messages: + msg81504
2009-02-09 21:32:41loewissetmessages: + msg81493
2009-02-09 21:26:30robindsetmessages: + msg81492
2009-01-21 06:48:46loewissetnosy: + loewis
messages: + msg80318
2009-01-21 02:00:38robindcreate