wx.ProgressDialog + py2exe leads to application crash
Question: This simple code runs very well :

    
    
    import wx
    app = wx.App(0)
    frame = wx.Frame(None)
    test = wx.ProgressDialog('Test', 'Test', maximum = 20, parent = frame, style = wx.PD_CAN_ABORT)
    app.MainLoop()
    

However, when compiling/packing it into an executable with `py2exe`...

    
    
    from distutils.core import setup
    import py2exe
    setup(script_args = ['py2exe'], windows=[{'script':'progressdlgprobblem.py'}],  
       options = {'py2exe': {'compressed':1,'bundle_files': 1}}, zipfile = None)
    

... then the `.exe` file crashes.

**What could be the cause of this crash? Does`wx.ProgressDialog` require some
specific additional elements in order to be used with `py2exe`?**

* * *

_Addendum 1_ : when I remove the `style = wx.PD_CAN_ABORT`, there is no more
crash. How can the crash come from the `style` ? But then, the _styling_ is
XP-style when launching from the `.exe` :

![enter image description here](http://i.stack.imgur.com/xXEo5.jpg)

and different to the styling I get when launching from the `.py` (without
py2exe) :

![enter image description here](http://i.stack.imgur.com/Rvpvq.jpg)

* * *

_Addendum 2_ : when I remove the `'bundle_files': 1`, no more crash. But I
would like to keep this bundling into one file only ! **How can this bundling
into a single .exe file be the cause of this crash ?**

_Addendum 3_ : A big part of the problem is solved by using wx.Python 3.0.1.0b
instead of 3.0.0.0 (more details soon).


Answer: py2exe (0.6.9) is pretty outdated and doesn't handle newer Windows versions
all that well without some additional changes. Specifically, it will by
default include some Windows system DLLs which never should be bundled. To
prevent this, try altering your setup script as follows:

    
    
    from distutils.core import setup
    import py2exe
    
    # Exclude system DLLs
    origIsSystemDLL = py2exe.build_exe.isSystemDLL
    def isSystemDLL(pathname):
        if os.path.basename(pathname).lower() in ("gdiplus.dll", 
                                                  "mfc90.dll"):
            return 0
        if os.path.basename(pathname).lower() in ("powrprof.dll", ) or \
           os.path.basename(pathname).lower().startswith("api-ms-win-"):
            return 1
        return origIsSystemDLL(pathname)
    py2exe.build_exe.isSystemDLL = isSystemDLL
    
    # Add the MS VC9 CRT and common controls manifest as resource to the exe
    manifest = '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
      <assemblyIdentity
        version="0.0.0.0"
        processorArchitecture="x86"
        name="Enter program name here"
        type="win32"
      />
      <description>Enter program description here</description>
      <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
        <security>
          <requestedPrivileges>
            <requestedExecutionLevel level="asInvoker" uiAccess="false" />
          </requestedPrivileges>
        </security>
      </trustInfo>
      <dependency>
        <dependentAssembly>
          <assemblyIdentity
             type="win32"
             name="Microsoft.Windows.Common-Controls"
             version="6.0.0.0"
             processorArchitecture="x86"
             publicKeyToken="6595b64144ccf1df"
             language="*"
           />
        </dependentAssembly>
      </dependency>
      <dependency>
        <dependentAssembly>
          <assemblyIdentity
             type="win32"
             name="Microsoft.VC90.CRT"
             version="9.0.21022.8"
             processorArchitecture="x86"
             publicKeyToken="1fc8b3b9a1e18e3b"
           />
        </dependentAssembly>
      </dependency>
    </assembly>
    '''
    
    setup(script_args=['py2exe'],
          windows=[{'script': 'progressdlgprobblem.py',
                    'other_resources': [(24, 1, manifest)]}],  
          options = {'py2exe': {'compressed': 1,
                                'dll_excludes': ['iertutil.dll', 
                                                 'MPR.dll',
                                                 'msvcm90.dll', 
                                                 'msvcp90.dll', 
                                                 'msvcr90.dll', 
                                                 'mswsock.dll',
                                                 'urlmon.dll',
                                                 'w9xpopen.exe'],
                                'bundle_files': 1}},
          zipfile=None)
    

For best interoperability, you'll also want to copy
Microsoft.VC90.CRT.manifest, msvcm90.dll, msvcp90.dll, and msvcr90.dll from
C:\Windows\winsxs\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.21022.8_none_bcb86ed6ac711f91
(the directory name may be slightly different, but the correct version
9.0.21022.8 is important) to your exe's directory so users don't need to
install the right version of the MS VC9 CRT themselves.

Alternatively to all of this, you could try PyInstaller which automatically
handles assembly dependencies and excludes system DLLs by default.

