Differences between revisions 2 and 3
Revision 2 as of 2008-07-08 11:27:43
Size: 3327
Editor: localhost
Comment: converted to 1.6 markup
Revision 3 as of 2010-07-30 00:51:16
Size: 3311
Editor: JorBratko
Comment: fixed bugs in sample code
Deletions are marked like this. Additions are marked like this.
Line 41: Line 41:
        idrsc='#%d'%idrsc         idrsc=u'#%d'%idrsc
Line 43: Line 43:
        typersc='#%d'%typersc         typersc=u'#%d'%typersc
Line 63: Line 63:
        return cast(self,POINTER(c_char*sizeof(self))[0].raw         return cast(pointer(self),POINTER(c_char*sizeof(self)))[0].raw
Line 67: Line 67:

in your setup file, you

How to add custom data into the executable?

Sometimes it is very useful to be able to insert binary data into the final executable. The most casual use case is to insert version strings into the binary without having to modify the main script source code.

This is done very simply by inserting a custom named resource into the executable such as shown in the example below. In this case, I chose "VERSIONTAG" but you are free to use any unicode string.

Example

from distutils.core import setup

myrevisionstring="prog internal rev 1.0"
setup(windows=[{'script': "prog.py", 
                'other_resources': [(u"VERSIONTAG",1,myrevisionstring)],
                             'icon_resources': [(1,'prog.ico')]
               }],
               zipfile = r"subdir\modules.dat",
               name="My Program",
               version="1.0",
     )

More fun with resources

For all the following, you must download and install the other excellemt module from ThomasHeller: ctypes

First you can define the following code in a separate module (winrsc.py for example)

from ctypes import *

def GetModuleHandle(filename=None):
    h=windll.kernel32.GetModuleHandleW(filename)
    if not h:
        raise WinError()
    return h

def FindResource(typersc,idrsc,c_restype=c_char,filename=None):
    if type(idrsc)is int:
        idrsc=u'#%d'%idrsc
    if type(typersc) is int:
        typersc=u'#%d'%typersc
    hmod=GetModuleHandle(filename)
    hrsc=windll.kernel32.FindResourceW(hmod,typersc,idrsc)
    if not hrsc:
        raise WinError()
    hglobal=windll.kernel32.LoadResource(hmod,hrsc)
    if not hglobal:
        raise WinError()
    windll.kernel32.LockResource.restype=POINTER(c_restype)
    return windll.kernel32.LockResource(hglobal)[0]

Then in another module, you create some kind of data structure. privdata.py

from ctypes import *

class MyPrivateInfo(Structure):
    _fields_ = [ ("ver",c_int),("debug",c_int),("copyright_info",c_char*100) ]
    def get_buffer(self):
        return cast(pointer(self),POINTER(c_char*sizeof(self)))[0].raw

And in your setup you can do.

import privdata

setup(windows=[{'script': "prog.py", 
                'other_resources': [(u"PRIVTAG",1,privdata.MyPrivateInfo(100,100,"My Copyright notice").get_buffer()],
                             'icon_resources': [(1,'prog.ico')]
               }],
               zipfile = r"subdir\modules.dat",
               name="My Program",
               version="1.0",
     )

This should insert a resource with the info that you give to the constructor of your private object.

Finally, at runtime in your frozen executable you can do:

import privdata
import winrsc
try:
    someinfo=winrsc.FindResource("PRIVTAG",1,c_restype=privdata.MyPrivateInfo)
except Exception,e:
    someinfo=None

if someinfo:
    print someinfo.ver
    print someinfo.copyright_info

This is quite useful if you want to have a single executable but different behaviour depending on a flag. For example, if a debug flag is set, you can choose to log all errors to the console instead of ignoring them etc.

CustomDataInExe (last edited 2010-07-30 00:51:16 by JorBratko)