Ticket #39: pyinstaller-trunk-r681-py26-win-tweaks-20090618.patch
| File pyinstaller-trunk-r681-py26-win-tweaks-20090618.patch, 58.3 KB (added by openticket, 15 months ago) |
|---|
-
application.config
1 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 2 <configuration> 3 <windows> 4 <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 5 <assemblyIdentity processorArchitecture="X86" name="Microsoft.Windows.mysampleApp" type="win32" version="1.0.0.0"/> 6 <publisherPolicy apply="no"/> 7 <dependentAssembly> 8 <assemblyIdentity type="win32" processorArchitecture="x86" name="Microsoft.Windows.SampleAssembly" publicKeyToken="0000000000000000"/> 9 <bindingRedirect oldVersion="2.0.0.0" newVersion="2.0.1.0"/> 10 </dependentAssembly> 11 </assemblyBinding> 12 </windows> 13 </configuration> 14 No newline at end of file -
application.manifest
1 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 2 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 3 <assemblyIdentity type="win32" 4 name="myOrganization.myDivision.mySampleApp" 5 version="6.0.0.0" 6 processorArchitecture="x86" 7 publicKeyToken="0000000000000000" 8 /> 9 <dependency> 10 <dependentAssembly> 11 <assemblyIdentity type="win32" 12 name="Proseware.Research.SampleAssembly" 13 version="6.0.0.0" 14 processorArchitecture="X86" 15 publicKeyToken="0000000000000000" 16 language="*" 17 /> 18 </dependentAssembly> 19 </dependency> 20 </assembly> 21 No newline at end of file -
apptemplate.manifest
1 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 2 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 3 <assemblyIdentity 4 version="0.0.0.0" 5 processorArchitecture="x86" 6 name="myOrganization.myDivision.mySampleApp" 7 type="win32" 8 /> 9 <description>Description</description> 10 <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> 11 <security> 12 <requestedPrivileges> 13 <requestedExecutionLevel level="asInvoker" uiAccess="false" /> 14 </requestedPrivileges> 15 </security> 16 </trustInfo> 17 <dependency> 18 <dependentAssembly> 19 <assemblyIdentity 20 type="win32" 21 name="Microsoft.Windows.Common-Controls" 22 version="6.0.0.0" 23 processorArchitecture="x86" 24 publicKeyToken="6595b64144ccf1df" 25 language="*" 26 /> 27 </dependentAssembly> 28 </dependency> 29 <dependency> 30 <dependentAssembly> 31 <assemblyIdentity 32 type="win32" 33 name="Microsoft.VC90.CRT" 34 version="9.0.21022.8" 35 processorArchitecture="x86" 36 publicKeyToken="1fc8b3b9a1e18e3b" 37 /> 38 </dependentAssembly> 39 </dependency> 40 </assembly> 41 No newline at end of file -
assembly.manifest
1 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 2 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" 3 manifestVersion="1.0"> 4 <assemblyIdentity type="win32" name="Microsoft.Tools.SampleAssembly" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="0000000000000000"/> 5 <file name="sampleu.dll" hash="3eab067f82504bf271ed38112a4ccdf46094eb5a" hashalg="SHA1"> 6 <comClass description="Font Property Page" clsid="{0BE35200-8F91-11CE-9DE3-00AA004BB851}"/> 7 <comClass description="Color Property Page" clsid="{0BE35201-8F91-11CE-9DE3-00AA004BB851}"/> 8 <comClass description="Picture Property Page" clsid="{0BE35202-8F91-11CE-9DE3-00AA004BB851}"/> 9 </file> 10 <file name="bar.dll" hash="ac72753e5bb20446d88a48c8f0aaae769a962338" hashalg="SHA1"/> 11 <file name="foo.dll" hash="a7312a1f6cfb46433001e0540458de60adcd5ec5" hashalg="SHA1"> 12 <comClass description="Registrar Class" clsid="{44EC053A-400F-11D0-9DCD-00A0C90391D3}" progid="ATL.Registrar"/> 13 <comInterfaceProxyStub iid="{B6EA2051-048A-11D1-82B9-00C04FB9942E}" name=" IAxWinAmbientDispatch " tlbid="{34EC053A-400F-11D0-9DCD-00A0C90391D3}"/> 14 <typelib tlbid="{44EC0535-400F-11D0-9DCD-00A0C90391D3}" version="1.0" helpdir=""/> 15 </file> 16 <file name="sampledll.dll" hash="ba62960ceb15073d2598379307aad84f3a73dfcb" hashalg="SHA1"/> 17 <windowClass>ToolbarWindow32</windowClass> 18 <windowClass>ComboBoxEx32</windowClass> 19 <windowClass>sample_trackbar32</windowClass> 20 <windowClass>sample_updown32</windowClass> 21 </assembly> 22 No newline at end of file -
bindepend.py
43 43 iswin = sys.platform[:3] == 'win' 44 44 cygwin = sys.platform == 'cygwin' 45 45 46 if iswin: 47 from manifest import RT_MANIFEST, GetManifestResources, ManifestFromXML 48 try: 49 import resource 50 except ImportError, detail: 51 resource = None 52 46 53 excludes = { 47 54 'KERNEL32.DLL':1, 48 55 'ADVAPI.DLL':1, … … 78 85 'PSAPI.DLL':1, 79 86 'MSVCP80.DLL':1, 80 87 'MSVCR80.DLL':1, 88 'IERTUTIL.DLL':1, 89 'POWRPROF.DLL':1, 90 'SHLWAPI.DLL':1, 91 'URLMON.DLL':1, 81 92 # regex excludes 82 93 # don't include in the bundle the libc and the tls stuff 83 94 r'^/usr/lib/tls':1, … … 87 98 r'/usr/lib/libGL.*':1, 88 99 # 89 100 '^/System/Library/Frameworks':1, 101 # MS assembly excludes 102 'Microsoft.Windows.Common-Controls':1, 90 103 } 91 104 92 105 excludesRe = re.compile('|'.join(excludes.keys()), re.I) … … 283 296 for lib, npth in selectImports(pth, platform, xtrapath): 284 297 if seen.get(string.upper(lib),0): 285 298 continue 299 if iswin: 300 for ftocnm, fn in selectAssemblies(npth): 301 lTOC.append((ftocnm, fn, 'BINARY')) 286 302 lTOC.append((lib, npth, 'BINARY')) 287 303 288 304 return lTOC 289 305 306 def selectAssemblies(npth): 307 """Return the dependent assemblies of a binary that should be included. 308 309 Return a list of pairs (name, fullpath) 310 """ 311 # check for manifest file 312 manifestnm = npth + ".manifest" 313 if os.path.isfile(manifestnm): 314 fd = open(manifestnm, "rb") 315 res = {RT_MANIFEST: {1: {0: fd.read()}}} 316 fd.close() 317 elif not resource: 318 # resource access unavailable (needs pywin32) 319 return [] 320 else: 321 # check the binary for embedded manifest 322 res = GetManifestResources(npth) 323 rv = [] 324 if RT_MANIFEST in res and len(res[RT_MANIFEST]): 325 for name in res[RT_MANIFEST]: 326 for language in res[RT_MANIFEST][name]: 327 # check the manifest for dependent assemblies 328 try: 329 manifest = ManifestFromXML(res[RT_MANIFEST][name][language]) 330 except Exception, exc: 331 print "E:", npth, str(exc) 332 pass 333 else: 334 for assembly in manifest.dependentAssemblies: 335 if assembly.optional or \ 336 excludesRe.search(assembly.name) or \ 337 seen.get(assembly.name.upper(),0): 338 #print "I: skipping assembly:", assembly.name, "dependency of", npth 339 continue 340 files = assembly.find_files() 341 if files: 342 seen[assembly.name.upper()] = 1 343 for fn in files: 344 fname, fext = os.path.splitext(fn) 345 if fext.lower() == ".manifest": 346 ftocnm = assembly.name + fext 347 else: 348 ftocnm = os.path.basename(fn) 349 ftocnm, fn = [item.encode(sys.getfilesystemencoding()) for item in (ftocnm, fn)] 350 if not excludesRe.search(ftocnm) and \ 351 not seen.get(ftocnm.upper(),0): 352 print "I: SRCPATH:", fn 353 print "I:", ftocnm, "part of assembly", assembly.name, "dependency of", npth 354 seen[ftocnm.upper()] = 1 355 rv.append((ftocnm, fn)) 356 else: 357 #print "I: skipping", ftocnm, "part of assembly", assembly.name, "dependency of", npth 358 pass 359 else: 360 print "E: assembly not found:", assembly.name, "dependency of", npth 361 return rv 362 290 363 def selectImports(pth, platform=sys.platform, xtrapath=None): 291 364 """Return the dependencies of a binary that should be included. 292 365 … … 302 375 iswin = platform[:3] == 'win' 303 376 for lib in dlls: 304 377 if not iswin and not cygwin: 305 # plain win case378 # all other platforms 306 379 npth = lib 307 380 dir, lib = os.path.split(lib) 308 381 if excludes.get(dir,0): 309 382 continue 310 383 else: 311 # all other platforms384 # plain win case 312 385 npth = getfullnameof(lib, xtrapath) 313 386 314 # now npth is a candidate lib 387 # now npth is a candidate lib if found 315 388 # check again for excludes but with regex FIXME: split the list 316 if excludesRe.search(npth): 317 if 'libpython' not in npth and 'Python.framework' not in npth: 389 candidatelib = npth if npth else lib 390 if excludesRe.search(candidatelib): 391 if 'libpython' not in candidatelib and 'Python.framework' not in candidatelib: 318 392 # skip libs not containing (libpython or Python.framework) 319 393 #print "I: skipping %20s <- %s" % (npth, pth) 320 394 continue … … 324 398 325 399 if npth: 326 400 rv.append((lib, npth)) 327 el se:401 elif not seen.get(lib.upper(),0): 328 402 print "E: lib not found:", lib, "dependency of", pth 329 403 330 404 return rv … … 375 449 """Forwards to the correct getImports implementation for the platform. 376 450 """ 377 451 if platform[:3] == 'win' or platform == 'cygwin': 378 return _getImports_pe(pth) 452 try: 453 return _getImports_pe(pth) 454 except: 455 # not a binary file - assemblies can pull in files which don't 456 # necessarily have a PE header, but are still needed by the 457 # assembly. Any additional binary dependencies will already have 458 # been handled by selectAssemblies, so just return an empty list. 459 return [] 379 460 elif platform == 'darwin': 380 461 return _getImports_otool(pth) 381 462 else: … … 461 542 import glob 462 543 for a in args: 463 544 for fn in glob.glob(a): 464 print fn, getImports(fn, opts.target_platform) 545 print fn, getImports(fn, opts.target_platform) 546 No newline at end of file -
Build.py
627 627 self.name = kws.get('name',None) 628 628 self.icon = kws.get('icon',None) 629 629 self.versrsrc = kws.get('version',None) 630 self.manifest = kws.get('manifest',None) 631 self.resources = kws.get('resources',[]) 630 632 self.strip = kws.get('strip',None) 631 633 self.upx = kws.get('upx',None) 632 634 self.crypt = kws.get('crypt', 0) … … 660 662 ('debug', _check_guts_eq), 661 663 ('icon', _check_guts_eq), 662 664 ('versrsrc', _check_guts_eq), 665 ('manifest', _check_guts_eq), 666 ('resources', _check_guts_eq), 663 667 ('strip', _check_guts_eq), 664 668 ('upx', _check_guts_eq), 665 669 ('crypt', _check_guts_eq), … … 679 683 if not data: 680 684 return True 681 685 682 icon, versrsrc = data[3:5]683 if (icon or versrsrc ) and not config['hasRsrcUpdate']:686 icon, versrsrc, manifest, resources = data[3:7] 687 if (icon or versrsrc or manifest or resources) and not config['hasRsrcUpdate']: 684 688 # todo: really ignore :-) 685 print "ignoring icon and versionresources = platform not capable"689 print "ignoring icon, version, manifest and resources = platform not capable" 686 690 687 691 mtm = data[-1] 688 692 crypt = data[-2] … … 722 726 exe = os.path.join(HOMEPATH, exe) 723 727 if target_iswin or cygwin: 724 728 exe = exe + '.exe' 725 if config['hasRsrcUpdate']: 729 if config['hasRsrcUpdate'] and (self.icon or self.versrsrc or 730 self.manifest or self.resources): 731 tmpnm = tempfile.mktemp() 732 shutil.copy2(exe, tmpnm) 733 os.chmod(tmpnm, 0755) 726 734 if self.icon: 727 tmpnm = tempfile.mktemp()728 shutil.copy2(exe, tmpnm)729 os.chmod(tmpnm, 0755)730 735 icon.CopyIcons(tmpnm, self.icon) 731 trash.append(tmpnm)732 exe = tmpnm733 736 if self.versrsrc: 734 tmpnm = tempfile.mktemp()735 shutil.copy2(exe, tmpnm)736 os.chmod(tmpnm, 0755)737 737 versionInfo.SetVersion(tmpnm, self.versrsrc) 738 trash.append(tmpnm) 739 exe = tmpnm 738 if self.manifest: 739 manifest.UpdateManifestResourcesFromXMLFile(tmpnm, self.manifest, [1]) 740 for res in self.resources: 741 res = res.split(",") 742 for i in range(len(res[1:])): 743 try: 744 res[i + 1] = int(res[i + 1]) 745 except ValueError: 746 pass 747 resfile = res[0] 748 restype = res[1] if len(res) > 1 else None 749 resname = res[2] if len(res) > 2 else None 750 reslang = res[3] if len(res) > 3 else None 751 try: 752 resource.UpdateResourcesFromResFile(tmpnm, resfile, 753 [restype or "*"], 754 [resname or "*"], 755 [reslang or "*"]) 756 except resource.pywintypes.error, exc: 757 if exc.args[0] != resource.ERROR_BAD_EXE_FORMAT: 758 print "E:", str(exc) 759 continue 760 if not restype or not resname: 761 print "E: resource type and/or name not specified" 762 continue 763 if "*" in (restype, resname): 764 print ("E: no wildcards allowed for resource type " 765 "and name when source file does not contain " 766 "resources") 767 continue 768 try: 769 resource.UpdateResourcesFromDataFile(tmpnm, 770 resfile, 771 restype, 772 [resname], 773 [reslang or 0]) 774 except resource.pywintypes.error, exc: 775 print "E:", str(exc) 776 trash.append(tmpnm) 777 exe = tmpnm 740 778 exe = checkCache(exe, self.strip, self.upx and config['hasUPX']) 741 779 self.copy(exe, outf) 742 780 if self.append_pkg: … … 749 787 os.chmod(self.name, 0755) 750 788 _save_data(self.out, 751 789 (self.name, self.console, self.debug, self.icon, 752 self.versrsrc, self. strip, self.upx, self.crypt, mtime(self.name)))790 self.versrsrc, self.manifest, self.resources, self.strip, self.upx, self.crypt, mtime(self.name))) 753 791 for item in trash: 754 792 os.remove(item) 755 793 return 1 … … 773 811 os.chmod(self.name, 0755) 774 812 _save_data(self.out, 775 813 (self.name, self.console, self.debug, self.icon, 776 self.versrsrc, self. strip, self.upx, mtime(self.name)))814 self.versrsrc, self.manifest, self.resources, self.strip, self.upx, mtime(self.name))) 777 815 return 1 778 816 779 817 … … 1022 1060 1023 1061 def main(specfile, configfilename): 1024 1062 global target_platform, target_iswin, config 1025 global icon, versionInfo 1063 global icon, versionInfo, resource, manifest 1026 1064 1027 1065 try: 1028 1066 config = _load_data(configfilename) … … 1046 1084 sys.exit(1) 1047 1085 1048 1086 if config['hasRsrcUpdate']: 1049 import icon, versionInfo 1087 import icon, versionInfo, resource, manifest 1050 1088 1051 1089 if config['hasUPX']: 1052 1090 setupUPXFlags() … … 1062 1100 parser.add_option('-C', '--configfile', 1063 1101 default=os.path.join(HOMEPATH, 'config.dat'), 1064 1102 help='Name of generated configfile (default: %default)') 1103 parser.add_option('-o', '--buildpath', 1104 default=None, 1105 help='Buildpath') 1065 1106 opts, args = parser.parse_args() 1066 1107 if len(args) != 1: 1067 1108 parser.error('Requires exactly one .spec-file') 1068 1109 1069 main(args[0], configfilename=opts.configfile) 1110 main(args[0], configfilename=opts.configfile) 1111 No newline at end of file -
Makespec.py
135 135 136 136 def main(scripts, configfile=None, name=None, tk=0, freeze=0, console=1, debug=0, 137 137 strip=0, upx=0, comserver=0, ascii=0, workdir=None, 138 pathex=[], version_file=None, icon_file=None, crypt=None):138 pathex=[], version_file=None, icon_file=None, manifest_file=None, resources=[], crypt=None): 139 139 140 140 try: 141 141 config = eval(open(configfile, 'r').read()) … … 168 168 exe_options = "%s, version='%s'" % (exe_options, quote_win_filepath(version_file)) 169 169 if icon_file: 170 170 exe_options = "%s, icon='%s'" % (exe_options, quote_win_filepath(icon_file)) 171 if manifest_file: 172 exe_options = "%s, manifest='%s'" % (exe_options, quote_win_filepath(manifest_file)) 173 if resources: 174 for i in range(len(resources)): 175 resources[i] = quote_win_filepath(resources[i]) 176 exe_options = "%s, resources=%s" % (exe_options, repr(resources)) 171 177 if not ascii and config['hasUnicode']: 172 178 scripts.insert(0, os.path.join(HOME, 'support', 'useUnicode.py')) 173 179 for i in range(len(scripts)): … … 278 284 dest="version_file", metavar="FILE", 279 285 help="add a version resource from FILE to the exe " 280 286 "(Windows only)") 281 g.add_option("- -icon", type="string", dest="icon_file",287 g.add_option("-i", "--icon", type="string", dest="icon_file", 282 288 metavar="FILE.ICO or FILE.EXE,ID", 283 289 help="If FILE is an .ico file, add the icon to the final " 284 290 "executable. Otherwise, the syntax 'file.exe,id' to " 285 291 "extract the icon with the specified id " 286 292 "from file.exe and add it to the final executable") 293 g.add_option("-m", "--manifest", type="string", 294 dest="manifest_file", metavar="FILE", 295 help="add manifest FILE to the exe " 296 "(Windows only)") 297 g.add_option("-r", "--resource", type="string", default=[], dest="resources", 298 metavar="FILE[,TYPE[,NAME[,LANGUAGE]]]", action="append", 299 help="add/update resource of the given type, name and language " 300 "from FILE to the final executable. FILE can be a " 301 "data file or an exe/dll. For data files, atleast " 302 "TYPE and NAME need to be specified, LANGUAGE defaults " 303 "to 0 or may be specified as wildcard * to update all " 304 "resources of the given TYPE and NAME. For exe/dll " 305 "files, all resources from FILE will be added/updated " 306 "to the final executable if TYPE, NAME and LANGUAGE " 307 "are omitted or specified as wildcard *." 308 "Multiple resources are allowed, using this option " 309 "multiple times.") 287 310 288 311 opts,args = p.parse_args() 289 312 -
manifest.py
1 #!/usr/bin/env python 2 3 """ 4 manifest.py 2009-03 Florian Hoech 5 6 Provides the following functionality: 7 * Create, parse and write MS Windows Manifest files 8 * Find files which are part of an assembly, by looking for shared and 9 private assemblies 10 * Update manifest resources in dll/exe files 11 12 Implemented: 13 * Shared and private assemblies support 14 * Publisher configuration support (.policy files) 15 * application configuration support (.config files) 16 17 Not implemented: 18 * Manifest validation (only very basic sanity checks are currently in place) 19 * comClass, typelib, comInterfaceProxyStub, windowClass subelements of the 20 file element 21 * comInterfaceExternalProxyStub, windowClass subelements of the assembly 22 element 23 24 Reference: 25 About Isolated Applications and Side-by-side Assemblies 26 http://msdn.microsoft.com/en-us/library/aa374029(VS.85).aspx 27 """ 28 try: 29 import hashlib 30 except ImportError, detail: 31 hashlib = None 32 print 'I: ... file hash calculation unavailable -', detail 33 import os.path 34 from glob import glob 35 from xml.dom import Node, minidom 36 from xml.dom.minidom import Document, Element 37 38 Document.aChild = Document.appendChild 39 Document.cE = Document.createElement 40 Document.cT = Document.createTextNode 41 Document.getEById = Document.getElementById 42 Document.getEByTN = Document.getElementsByTagName 43 Element.aChild = Element.appendChild 44 Element.getA = Element.getAttribute 45 Element.getEByTN = Element.getElementsByTagName 46 Element.remA = Element.removeAttribute 47 Element.setA = Element.setAttribute 48 49 try: 50 import resource 51 except ImportError, detail: 52 resource = None 53 print 'I: ... manifest resource access unavailable -', detail 54 55 RT_MANIFEST = 24 56 57 def getChildElementsByTagName(self, tagName): 58 """ Return child elements of type tagName if found, else [] """ 59 result = [] 60 for child in self.childNodes: 61 if isinstance(child, Element): 62 if child.tagName == tagName: 63 result.append(child) 64 return result 65 66 def getFirstChildElementByTagName(self, tagName): 67 """ Return the first element of type tagName if found, else None """ 68 for child in self.childNodes: 69 if isinstance(child, Element): 70 if child.tagName == tagName: 71 return child 72 return None 73 74 Document.getCEByTN = getChildElementsByTagName 75 Document.getFCEByTN = getFirstChildElementByTagName 76 Element.getCEByTN = getChildElementsByTagName 77 Element.getFCEByTN = getFirstChildElementByTagName 78 79 class _Dummy: 80 pass 81 82 class File(resource.File if resource else _Dummy): 83 """ A file referenced by an assembly inside a manifest. """ 84 def __init__(self, filename="", hashalg=None, hash=None, comClasses=None, 85 typelibs=None, comInterfaceProxyStubs=None, 86 windowClasses=None): 87 if resource: 88 resource.File.__init__(self, filename) 89 else: 90 self.filename = filename 91 self.name = os.path.basename(filename) 92 self.hashalg = hashalg.upper() if hashalg else None 93 if os.path.isfile(filename) and hashalg and hashlib: 94 self.calc_hash() 95 else: 96 self.hash = hash 97 self.comClasses = comClasses or [] # TO-DO: implement 98 self.typelibs = typelibs or [] # TO-DO: implement 99 self.comInterfaceProxyStubs = comInterfaceProxyStubs or [] # TO-DO: implement 100 self.windowClasses = windowClasses or [] # TO-DO: implement 101 def calc_hash(self, hashalg=None): 102 """ Calculate the hash of the file. Will be called automatically from 103 the constructor if the file exists and hashalg is given, but may 104 also be called manually e.g. to update the hash if the file has 105 changed. """ 106 fd = open(self.filename, "rb") 107 buf = fd.read() 108 fd.close() 109 if hashalg: 110 self.hashalg = hashalg.upper() 111 self.hash = getattr(hashlib, self.hashalg.lower())(buf).hexdigest() 112 113 class InvalidManifestError(Exception): 114 pass 115 116 class Manifest(): 117 def __init__(self, manifestVersion=None, noInheritable=False, 118 noInherit=False, type_=None, name=None, language=None, 119 processorArchitecture=None, version=None, 120 publicKeyToken=None, description=None, 121 requestedExecutionLevel=None, uiAccess=None, 122 dependentAssemblies=None, files=None, 123 comInterfaceExternalProxyStubs=None): 124 """ Manifest constructor. 125 126 To build a basic manifest for your application: 127 mf = Manifest(type='win32', name='YourAppName', language='*', 128 processorArchitecture='x86', version=[1, 0, 0, 0]) 129 130 To write the XML to a manifest file: 131 mf.writexml("YourAppName.exe.manifest") 132 or 133 mf.writeprettyxml("YourAppName.exe.manifest") 134 """ 135 self.filename = None 136 self.optional = None 137 self.manifestType = "assembly" 138 self.manifestVersion = manifestVersion or [1, 0] 139 self.noInheritable = noInheritable 140 self.noInherit = noInherit 141 self.type = type_ 142 self.name = name 143 self.language = language 144 self.processorArchitecture = processorArchitecture 145 self.version = version 146 self.publicKeyToken = publicKeyToken 147 # public key token 148 # "A 16-character hexadecimal string that represents the last 8 bytes 149 # of the SHA-1 hash of the public key under which the assembly is 150 # signed. The public key used to sign the catalog must be 2048 bits 151 # or greater. Required for all shared side-by-side assemblies." 152 # http://msdn.microsoft.com/en-us/library/aa375692(VS.85).aspx 153 self.applyPublisherPolicy = None 154 self.description = None 155 self.requestedExecutionLevel = requestedExecutionLevel 156 self.uiAccess = uiAccess 157 self.dependentAssemblies = dependentAssemblies or [] 158 self.bindingRedirects = [] 159 self.files = files or [] 160 self.comInterfaceExternalProxyStubs = comInterfaceExternalProxyStubs or [] # TO-DO: implement 161 162 def add_dependent_assembly(self, manifestVersion=None, noInheritable=False, 163 noInherit=False, type_=None, name=None, language=None, 164 processorArchitecture=None, version=None, 165 publicKeyToken=None, description=None, 166 requestedExecutionLevel=None, uiAccess=None, 167 dependentAssemblies=None, files=None, 168 comInterfaceExternalProxyStubs=None): 169 """ Shortcut for: 170 manifest.dependentAssemblies.append(Manifest(*args, *kwargs)) """ 171 self.dependentAssemblies.append(Manifest(manifestVersion, 172 noInheritable, noInherit, type_, name, 173 language, processorArchitecture, 174 version, publicKeyToken, description, 175 requestedExecutionLevel, uiAccess, 176 dependentAssemblies, files, 177 comInterfaceExternalProxyStubs)) 178 179 def add_file(self, name="", hashalg="", hash="", comClasses=None, 180 typelibs=None, comInterfaceProxyStubs=None, 181 windowClasses=None): 182 """ Shortcut for: 183 manifest.files.append(File(*args, *kwargs)) """ 184 self.files.append(File(name, hashalg, hash, comClasses, 185 typelibs, comInterfaceProxyStubs, windowClasses)) 186 187 def find_files(self): 188 """ Search shared and private assemblies and return a list of all 189 related files if found. If any files are not found, return an empty 190 list.""" 191 if None in (self.processorArchitecture, self.name, self.publicKeyToken, 192 self.version): 193 return [] 194 files = [] 195 # search winsxs 196 winsxs = os.path.join(os.getenv('SystemRoot'), 'WinSxS') 197 if os.path.isdir(winsxs): 198 manifests = os.path.join(winsxs, "Manifests") 199 if os.path.isdir(manifests): 200 for manifestpth in glob(os.path.join(manifests, 201 '%s_%s_%s_%s_*.manifest' % 202 (self.processorArchitecture, 203 self.name, 204 self.publicKeyToken, 205 ".".join([str(i) for i in self.version])))): 206 assemblynm = os.path.basename(os.path.splitext(manifestpth)[0]) 207 if not os.path.isfile(manifestpth): 208 print "W: No such file", manifestpth, "part of assembly", assemblynm 209 continue 210 print "I: Found manifest", manifestpth 211 assemblydir = os.path.join(winsxs, assemblynm) 212 if not os.path.isdir(assemblydir): 213 print "W: No such dir", assemblydir 214 continue 215 try: 216 manifest = ManifestFromXMLFile(manifestpth) 217 except Exception, exc: 218 print "E:", manifestpth, str(exc) 219 pass 220 else: 221 rfiles = [] 222 for file_ in self.files or manifest.files: 223 fn = os.path.join(assemblydir, file_.name) 224 if os.path.isfile(fn): 225 rfiles.append(fn) 226 else: 227 print "W: No such file", fn, "part of assembly", assemblynm 228 # if any of our files does not exist, 229 # the assembly is incomplete 230 rfiles = [] 231 break 232 if rfiles: 233 files.append(manifestpth) 234 files.extend(rfiles) 235 return files 236 break 237 else: 238 print "W: No such dir", manifests 239 else: 240 print "W: No such dir", winsxs 241 # search for private assemblies 242 if not self.filename: 243 return [] 244 dirnm = os.path.dirname(self.filename) 245 # if embedded in a dll the assembly may have the same name as the 246 # dll, so we need to make sure we don't search for *.dll.dll 247 assemblynm, ext = os.path.splitext(self.name) 248 if ext.lower() == ".dll": 249 # discard the extension 250 pass 251 else: 252 assemblynm = self.name 253 for path in [os.path.join(dirnm, self.language or "*"), 254 os.path.join(dirnm, self.language or "*", assemblynm), 255 dirnm, 256 os.path.join(dirnm, assemblynm)]: 257 for ext in (".dll", ".manifest"): 258 # private assemblies can have the manifest either as 259 # separate file or embedded in a DLL 260 manifestpth = os.path.join(path, assemblynm + ext) 261 if not os.path.isfile(manifestpth): 262 print "W: No such file", manifestpth, "part of assembly", assemblynm 263 continue 264 print "I: Found manifest", manifestpth 265 try: 266 if ext == ".dll": 267 manifest = ManifestFromResFile(manifestpth, [1]) 268 else: 269 manifest = ManifestFromXMLFile(manifestpth) 270 except Exception, exc: 271 print "E:", manifestpth, str(exc) 272 pass 273 else: 274 rfiles = [] 275 for file_ in self.files or manifest.files: 276 fn = os.path.join(path, file_.name) 277 if os.path.isfile(fn): 278 rfiles.append(fn) 279 else: 280 print "W: No such file", fn, "part of assembly", assemblynm 281 # if any of our files does not exist, 282 # the assembly is incomplete 283 return [] 284 files.append(manifestpth) 285 files.extend(rfiles) 286 break 287 if not os.path.isfile(manifestpth): 288 for file_ in self.files: 289 fn = os.path.join(path, file_.name) 290 if os.path.exists(fn): 291 # if any of our files does exist without the manifest 292 # in the same dir, the assembly is incomplete 293 return [] 294 return files 295 296 def load_dom(self, domtree, initialize=True): 297 """ Load manifest from DOM tree. 298 If initialize is True (default), reset existing attributes first.""" 299 if domtree.nodeType == Node.DOCUMENT_NODE: 300 rootElement = domtree.documentElement 301 elif domtree.nodeType == Node.ELEMENT_NODE: 302 rootElement = domtree 303 else: 304 raise InvalidManifestError("Invalid root element node type " + 305 str(rootElement.nodeType) + 306 " - has to be one of (DOCUMENT_NODE, ELEMENT_NODE)") 307 allowed_names = ("assembly", "assemblyBinding", "configuration", 308 "dependentAssembly") 309 if rootElement.tagName not in allowed_names: 310 raise InvalidManifestError("Invalid root element <" + 311 rootElement.tagName + 312 "> - has to be one of " + 313 repr(allowed_names)) 314 # print "I: loading manifest metadata from element <%s>" % \ 315 # rootElement.tagName 316 if rootElement.tagName == "configuration": 317 for windows in rootElement.getCEByTN("windows"): 318 for assemblyBinding in windows.getCEByTN("assemblyBinding"): 319 self.load_dom(assemblyBinding) 320 else: 321 if initialize: 322 self.__init__() 323 self.manifestType = rootElement.tagName 324 self.manifestVersion = [int(i) for i in (rootElement.getA("manifestVersion") or "1.0").split(".")] 325 self.noInheritable = bool(rootElement.getFCEByTN("noInheritable")) 326 self.noInherit = bool(rootElement.getFCEByTN("noInherit")) 327 for assemblyIdentity in rootElement.getCEByTN("assemblyIdentity"): 328 self.type = assemblyIdentity.getA("type") 329 self.name = assemblyIdentity.getA("name") 330 self.language = assemblyIdentity.getA("language") 331 self.processorArchitecture = assemblyIdentity.getA("processorArchitecture") 332 self.version = [int(i) for i in (assemblyIdentity.getA("version") or "0.0.0.0").split(".")] 333 self.publicKeyToken = assemblyIdentity.getA("publicKeyToken") 334 for publisherPolicy in rootElement.getCEByTN("publisherPolicy"): 335 self.applyPublisherPolicy = (publisherPolicy.getA("apply") or "").lower() == "yes" 336 for description in rootElement.getCEByTN("description"): 337 if description.firstChild: 338 self.description = description.firstChild.wholeText 339 for trustInfo in rootElement.getCEByTN("trustInfo"): 340 for security in trustInfo.getCEByTN("security"): 341 for requestedPrivileges in security.getCEByTN("requestedPrivileges"): 342 for requestedExecutionLevel in requestedPrivileges.getCEByTN("requestedExecutionLevel"): 343 self.requestedExecutionLevel = requestedExecutionLevel.getA("level") 344 self.uiAccess = (requestedExecutionLevel.getA("uiAccess") or "").lower() == "true" 345 for dependency in (rootElement.getCEByTN("dependency") if 346 rootElement.tagName != "assemblyBinding" else 347 [rootElement]): 348 for dependentAssembly in dependency.getCEByTN("dependentAssembly"): 349 manifest = ManifestFromDOM(dependentAssembly) 350 manifest.optional = (dependency.getA("optional") or "").lower() == "yes" 351 self.dependentAssemblies.append(manifest) 352 for bindingRedirect in rootElement.getCEByTN("bindingRedirect"): 353 oldVersion = [[int(i) for i in part.split(".")] for part in bindingRedirect.getA("oldVersion").split("-")] 354 newVersion = [int(i) for i in bindingRedirect.getA("newVersion").split(".")] 355 self.bindingRedirects.append((oldVersion, newVersion)) 356 for file_ in rootElement.getCEByTN("file"): 357 self.add_file(name=file_.getA("name"), 358 hashalg=file_.getA("hashalg"), 359 hash=file_.getA("hash")) 360 361 def parse(self, filename_or_file): 362 """ Load manifest from file or file object """ 363 self.load_dom(minidom.parse(filename_or_file)) 364 if isinstance(filename_or_file, (str, unicode)): 365 self.filename = filename_or_file 366 else: 367 self.filename = filename_or_file.filename 368 369 def parse_string(self, xmlstr): 370 """ Load manifest from XML string """ 371 self.load_dom(minidom.parseString(xmlstr)) 372 373 def todom(self): 374 """ Return the manifest as DOM tree """ 375 doc = Document() 376 docE = doc.cE(self.manifestType) 377 if self.manifestType == "assemblyBinding": 378 cfg = doc.cE("configuration") 379 win = doc.cE("windows") 380 win.aChild(docE) 381 cfg.aChild(win) 382 doc.aChild(cfg) 383 else: 384 doc.aChild(docE) 385 if self.manifestType != "dependentAssembly": 386 docE.setA("xmlns", "urn:schemas-microsoft-com:asm.v1") 387 if self.manifestType != "assemblyBinding": 388 docE.setA("manifestVersion", 389 ".".join([str(i) for i in self.manifestVersion])) 390 if self.noInheritable: 391 docE.aChild(doc.cE("noInheritable")) 392 if self.noInherit: 393 docE.aChild(doc.cE("noInherit")) 394 aId = doc.cE("assemblyIdentity") 395 if self.type: 396 aId.setAttribute("type", self.type) 397 if self.name: 398 aId.setAttribute("name", self.name) 399 if self.language: 400 aId.setAttribute("language", self.language) 401 if self.processorArchitecture: 402 aId.setAttribute("processorArchitecture", 403 self.processorArchitecture) 404 if self.version: 405 aId.setAttribute("version", 406 ".".join([str(i) for i in self.version])) 407 if self.publicKeyToken: 408 aId.setAttribute("publicKeyToken", self.publicKeyToken) 409 if aId.hasAttributes(): 410 docE.aChild(aId) 411 else: 412 aId.unlink() 413 if self.applyPublisherPolicy != None: 414 ppE = doc.cE("publisherPolicy") 415 ppE.setA("apply", "yes" if self.applyPublisherPolicy else "no") 416 docE.aChild(ppE) 417 if self.description: 418 descE = doc.cE("description") 419 descE.aChild(doc.cT(self.description)) 420 docE.aChild(descE) 421 if self.requestedExecutionLevel in ("asInvoker", "highestAvailable", 422 "requireAdministrator"): 423 tE = doc.cE("trustInfo") 424 tE.setA("xmlns", "urn:schemas-microsoft-com:asm.v3") 425 sE = doc.cE("security") 426 rpE = doc.cE("requestedPrivileges") 427 relE = doc.cE("requestedExecutionLevel") 428 relE.setA("level", self.requestedExecutionLevel) 429 relE.setA("uiAccess", "true" if self.uiAccess else "false") 430 rpE.aChild(relE) 431 sE.aChild(rpE) 432 tE.aChild(sE) 433 docE.aChild(tE) 434 if self.dependentAssemblies: 435 for assembly in self.dependentAssemblies: 436 if self.manifestType != "assemblyBinding": 437 dE = doc.cE("dependency") 438 if assembly.optional: 439 dE.setAttribute("optional", "yes") 440 daE = doc.cE("dependentAssembly") 441 adom = assembly.todom() 442 for child in adom.documentElement.childNodes: 443 daE.aChild(child.cloneNode(False)) 444 adom.unlink() 445 if self.manifestType != "assemblyBinding": 446 dE.aChild(daE) 447 docE.aChild(dE) 448 else: 449 docE.aChild(daE) 450 if self.bindingRedirects: 451 for bindingRedirect in self.bindingRedirects: 452 brE = doc.cE("bindingRedirect") 453 brE.setAttribute("oldVersion", 454 "-".join(".".join(str(i) for i in part) for part in bindingRedirect[0])) 455 brE.setAttribute("newVersion", 456 ".".join(str(i) for i in bindingRedirect[1])) 457 docE.aChild(brE) 458 if self.files: 459 for file_ in self.files: 460 fE = doc.cE("file") 461 for attr in ("name", "hashalg", "hash"): 462 val = getattr(file_, attr) 463 if val: 464 fE.setA(attr, val) 465 docE.aChild(fE) 466 return doc 467 468 def toprettyxml(self, indent=" ", newl=os.linesep, encoding="UTF-8"): 469 """ Return the manifest as pretty-printed XML """ 470 domtree = self.todom() 471 # WARNING: The XML declaration has to follow the order version-encoding-standalone (standalone being optional), 472 # otherwise if it is embedded in an exe the exe will fail to launch! ('application configuration incorrect') 473 xmlstr = domtree.toprettyxml(indent, newl, encoding).strip(os.linesep).replace('<?xml version="1.0" encoding="UTF-8"?>', 474 '<?xml version="1.0" encoding="%s" standalone="yes"?>' % encoding) 475 domtree.unlink() 476 return xmlstr 477 478 def toxml(self, encoding="UTF-8"): 479 """ Return the manifest as XML """ 480 domtree = self.todom() 481 # WARNING: The XML declaration has to follow the order version-encoding-standalone (standalone being optional), 482 # otherwise if it is embedded in an exe the exe will fail to launch! ('application configuration incorrect') 483 xmlstr = domtree.toxml(encoding).replace('<?xml version="1.0" encoding="UTF-8"?>', 484 '<?xml version="1.0" encoding="%s" standalone="yes"?>' % encoding) 485 domtree.unlink() 486 return xmlstr 487 488 def update_resources(self, dstpath, names=None, languages=None): 489 """ Update or add manifest to dll/exe file dstpath, as manifest 490 resource """ 491 UpdateManifestResourcesFromXML(dstpath, self.toprettyxml(), names, 492 languages) 493 494 def writeprettyxml(self, filename_or_file, indent=" ", newl=os.linesep, encoding="UTF-8"): 495 """ Write the manifest as XML to a file or file object """ 496 if isinstance(filename_or_file, (str, unicode)): 497 filename_or_file = open(filename_or_file, "wb") 498 xmlstr = self.toprettyxml(indent, newl, encoding) 499 filename_or_file.write(xmlstr) 500 filename_or_file.close() 501 502 def writexml(self, filename_or_file, indent=" ", newl=os.linesep, encoding="UTF-8"): 503 """ Write the manifest as XML to a file or file object """ 504 if isinstance(filename_or_file, (str, unicode)): 505 filename_or_file = open(filename_or_file, "wb") 506 xmlstr = self.toxml(indent, newl, encoding) 507 filename_or_file.write(xmlstr) 508 filename_or_file.close() 509 510 def ManifestFromResFile(filename, names=None, languages=None): 511 """ Create and return manifest instance from manifest resource in 512 dll/exe file """ 513 res = GetManifestResources(filename, names, languages) 514 if res and res[RT_MANIFEST]: 515 while isinstance(res, dict) and res.keys(): 516 res = res[res.keys()[0]] 517 if isinstance(res, dict): 518 raise InvalidManifestError("No manifest resource found in '%s'" % 519 filename) 520 manifest = ManifestFromXML(res) 521 manifest.filename = filename 522 return manifest 523 524 def ManifestFromDOM(domtree): 525 """ Create and return manifest instance from DOM tree """ 526 manifest = Manifest() 527 manifest.load_dom(domtree) 528 return manifest 529 530 def ManifestFromXML(xmlstr): 531 """ Create and return manifest instance from XML """ 532 manifest = Manifest() 533 manifest.parse_string(xmlstr) 534 return manifest 535 536 def ManifestFromXMLFile(filename_or_file): 537 """ Create and return manifest instance from manifest file """ 538 manifest = Manifest() 539 manifest.parse(filename_or_file) 540 return manifest 541 542 def GetManifestResources(filename, names=None, languages=None): 543 """ Get manifest resources from dll/exe file """ 544 return resource.GetResources(filename, [RT_MANIFEST], names, languages) 545 546 def UpdateManifestResourcesFromXML(dstpath, xmlstr, names=None, 547 languages=None): 548 """ Update or add manifest XML to dll/exe file dstpath, as manifest 549 resource """ 550 print "I: Updating manifest in", dstpath 551 name = 1 if dstpath.lower().endswith(".exe") else 2 552 resource.UpdateResources(dstpath, xmlstr, RT_MANIFEST, names or [name], 553 languages or [0, "*"]) 554 555 def UpdateManifestResourcesFromXMLFile(dstpath, srcpath, names=None, 556 languages=None): 557 """ Update or add manifest XML from file srcpath to dll/exe file 558 dstpath, as manifest resource """ 559 print "I: Updating manifest from", srcpath, "to", dstpath 560 name = 1 if dstpath.lower().endswith(".exe") else 2 561 resource.UpdateResourcesFromDataFile(dstpath, srcpath, RT_MANIFEST, 562 names or [name], 563 languages or [0, "*"]) 564 565 if __name__ == "__main__": 566 import sys 567 568 dstpath = sys.argv[1] 569 srcpath = sys.argv[2] 570 UpdateManifestResourcesFromXMLFile(dstpath, srcpath) 571 No newline at end of file -
publisher.policy
1 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 2 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 3 <assemblyIdentity type="win32-policy" publicKeyToken="0000000000000000" name="policy.2.0.Microsoft.Windows.SampleAssembly" version="1.1.0.0" processorArchitecture="x86"/> 4 <dependency> 5 <dependentAssembly> 6 <assemblyIdentity type="win32" name="Microsoft.Windows.SampleAssembly" processorArchitecture="x86" publicKeyToken="75e377300ab7b886"/> 7 <bindingRedirect oldVersion="2.0.0.0" newVersion="2.0.1.0"/> 8 </dependentAssembly> 9 </dependency> 10 </assembly> 11 No newline at end of file -
resource.py
1 #!/usr/bin/env python 2 3 import os.path 4 import pywintypes 5 import win32api 6 7 LOAD_LIBRARY_AS_DATAFILE = 2 8 ERROR_BAD_EXE_FORMAT = 193 9 ERROR_RESOURCE_DATA_NOT_FOUND = 1812 10 ERROR_RESOURCE_TYPE_NOT_FOUND = 1813 11 ERROR_RESOURCE_NAME_NOT_FOUND = 1814 12 ERROR_RESOURCE_LANG_NOT_FOUND = 1815 13 14 class File(): 15 def __init__(self, filename): 16 self.filename = filename 17 18 def get_resources(self, types=None, names=None, languages=None): 19 """ Get resources. 20 types = a list of resource types to search for (None = all) 21 names = a list of resource names to search for (None = all) 22 languages = a list of resource languages to search for (None = all) 23 Return a dict of the form {type_: {name: {language: data}}} which 24 might also be empty if no matching resources were found.""" 25 return GetResources(self.filename, types, names, languages) 26 27 def update_resources(self, data, type_, names=None, languages=None): 28 """ Update or add resource data. 29 type_ = resource type to update 30 names = a list of resource names to update (None = all) 31 languages = a list of resource languages to update (None = all)""" 32 UpdateResources(self.filename, data, type_, names, languages) 33 34 def update_resources_from_datafile(self, srcpath, type_, names=None, 35 languages=None): 36 """ Update or add resource data from file srcpath. 37 type_ = resource type to update 38 names = a list of resource names to update (None = all) 39 languages = a list of resource languages to update (None = all)""" 40 UpdateResourcesFromDataFile(self.filename, srcpath, type_, names, 41 languages) 42 43 def update_resources_from_dict(self, res, types=None, names=None, 44 languages=None): 45 """ Update or add resources from resource dict. 46 types = a list of resource types to update (None = all) 47 names = a list of resource names to update (None = all) 48 languages = a list of resource languages to update (None = all)""" 49 UpdateResourcesFromDict(self.filename, res, types, names, 50 languages) 51 52 def update_resources_from_resfile(self, srcpath, types=None, names=None, 53 languages=None): 54 """ Update or add resources from dll/exe file srcpath. 55 types = a list of resource types to update (None = all) 56 names = a list of resource names to update (None = all) 57 languages = a list of resource languages to update (None = all)""" 58 UpdateResourcesFromResFile(self.filename, srcpath, types, names, 59 languages) 60 61 def _GetResources(hsrc, types=None, names=None, languages=None): 62 """ Get resources from hsrc. 63 types = a list of resource types to search for (None = all) 64 names = a list of resource names to search for (None = all) 65 languages = a list of resource languages to search for (None = all) 66 Return a dict of the form {type_: {name: {language: data}}} which 67 might also be empty if no matching resources were found.""" 68 res = {} 69 try: 70 # print "I: Enumerating resource types" 71 enum_types = win32api.EnumResourceTypes(hsrc) 72 if types and not "*" in types: 73 enum_types = filter(lambda type_: 74 type_ in types, 75 enum_types) 76 for type_ in enum_types: 77 # print "I: Enumerating resources of type", type_ 78 enum_names = win32api.EnumResourceNames(hsrc, type_) 79 if names and not "*" in names: 80 enum_names = filter(lambda name: 81 name in names, 82 enum_names) 83 for name in enum_names: 84 # print "I: Enumerating resources of type", type_, "name", name 85 enum_languages = win32api.EnumResourceLanguages(hsrc, 86 type_, 87 name) 88 if languages and not "*" in languages: 89 enum_languages = filter(lambda language: 90 language in languages, 91 enum_languages) 92 for language in enum_languages: 93 data = win32api.LoadResource(hsrc, type_, name, language) 94 if not type_ in res: 95 res[type_] = {} 96 if not name in res[type_]: 97 res[type_][name] = {} 98 res[type_][name][language] = data 99 except pywintypes.error, exception: 100 if exception.args[0] in (ERROR_RESOURCE_DATA_NOT_FOUND, 101 ERROR_RESOURCE_TYPE_NOT_FOUND, 102 ERROR_RESOURCE_NAME_NOT_FOUND, 103 ERROR_RESOURCE_LANG_NOT_FOUND): 104 # print "I:", exception.args[1] + ":", \ 105 # exception.args[2] 106 pass 107 else: 108 raise exception 109 return res 110 111 def GetResources(filename, types=None, names=None, languages=None): 112 """ Get resources from dll/exe file. 113 types = a list of resource types to search for (None = all) 114 names = a list of resource names to search for (None = all) 115 languages = a list of resource languages to search for (None = all) 116 Return a dict of the form {type_: {name: {language: data}}} which 117 might also be empty if no matching resources were found.""" 118 hsrc = win32api.LoadLibraryEx(filename, 0, LOAD_LIBRARY_AS_DATAFILE) 119 res = _GetResources(hsrc, types, names, languages) 120 win32api.FreeLibrary(hsrc) 121 return res 122 123 def UpdateResources(dstpath, data, type_, names=None, languages=None): 124 """ Update or add resource data to dll/exe file dstpath. 125 type_ = resource type to update 126 names = a list of resource names to update (None = all) 127 languages = a list of resource languages to update (None = all)""" 128 # look for existing resources 129 res = GetResources(dstpath, [type_], names, languages) 130 # add type_, names and languages not already present in existing resources 131 if not type_ in res and type_ != "*": 132 res[type_] = {} 133 if names: 134 for name in names: 135 if not name in res[type_] and name != "*": 136 res[type_][name] = [] 137 if languages: 138 for language in languages: 139 if not language in res[type_][name] and language != "*": 140 res[type_][name].append(language) 141 # add resource to destination, overwriting existing resources 142 hdst = win32api.BeginUpdateResource(dstpath, 0) 143 for type_ in res: 144 for name in res[type_]: 145 for language in res[type_][name]: 146 print "I: Updating resource type", type_, "name", name, "language", language 147 win32api.UpdateResource(hdst, type_, name, data, language) 148 win32api.EndUpdateResource(hdst, 0) 149 150 def UpdateResourcesFromDataFile(dstpath, srcpath, type_, names=None, 151 languages=None): 152 """ Update or add resource data from file srcpath to dll/exe file 153 dstpath. 154 type_ = resource type to update 155 names = a list of resource names to update (None = all) 156 languages = a list of resource languages to update (None = all)""" 157 src = open(srcpath, "rb") 158 data = src.read() 159 src.close() 160 UpdateResources(dstpath, data, type_, names, languages) 161 162 def UpdateResourcesFromDict(dstpath, res, types=None, names=None, 163 languages=None): 164 """ Update or add resources from resource dict to dll/exe file 165 dstpath. 166 types = a list of resource types to update (None = all) 167 names = a list of resource names to update (None = all) 168 languages = a list of resource languages to update (None = all)""" 169 for type_ in res: 170 if not types or type_ in types: 171 for name in res[type_]: 172 if not names or name in names: 173 for language in res[type_][name]: 174 if not languages or language in languages: 175 UpdateResources(dstpath, 176 res[type_][name][language], 177 [type_], [name], [language]) 178 179 def UpdateResourcesFromResFile(dstpath, srcpath, types=None, names=None, 180 languages=None): 181 """ Update or add resources from dll/exe file srcpath to dll/exe file 182 dstpath. 183 types = a list of resource types to update (None = all) 184 names = a list of resource names to update (None = all) 185 languages = a list of resource languages to update (None = all)""" 186 res = GetResources(srcpath, types, names, languages) 187 UpdateResourcesFromDict(dstpath, res) 188 No newline at end of file
