/Tools/msi/merge.py

http://unladen-swallow.googlecode.com/ · Python · 84 lines · 70 code · 8 blank · 6 comment · 15 complexity · 4b236b8a8ee54b4c917d0f0e195828af MD5 · raw file

  1. import msilib,os,win32com,tempfile,sys
  2. PCBUILD="PCBuild"
  3. certname = None
  4. from config import *
  5. Win64 = "amd64" in PCBUILD
  6. mod_dir = os.path.join(os.environ["ProgramFiles"], "Common Files", "Merge Modules")
  7. msi = None
  8. if len(sys.argv)==2:
  9. msi = sys.argv[1]
  10. if Win64:
  11. modules = ["Microsoft_VC90_CRT_x86_x64.msm", "policy_9_0_Microsoft_VC90_CRT_x86_x64.msm"]
  12. if not msi: msi = "python-%s.amd64.msi" % full_current_version
  13. else:
  14. modules = ["Microsoft_VC90_CRT_x86.msm","policy_9_0_Microsoft_VC90_CRT_x86.msm"]
  15. if not msi: msi = "python-%s.msi" % full_current_version
  16. for i, n in enumerate(modules):
  17. modules[i] = os.path.join(mod_dir, n)
  18. def merge(msi, feature, rootdir, modules):
  19. cab_and_filecount = []
  20. # Step 1: Merge databases, extract cabfiles
  21. m = msilib.MakeMerge2()
  22. m.OpenLog("merge.log")
  23. print "Opened Log"
  24. m.OpenDatabase(msi)
  25. print "Opened DB"
  26. for module in modules:
  27. print module
  28. m.OpenModule(module,0)
  29. print "Opened Module",module
  30. m.Merge(feature, rootdir)
  31. print "Errors:"
  32. for e in m.Errors:
  33. print e.Type, e.ModuleTable, e.DatabaseTable
  34. print " Modkeys:",
  35. for s in e.ModuleKeys: print s,
  36. print
  37. print " DBKeys:",
  38. for s in e.DatabaseKeys: print s,
  39. print
  40. cabname = tempfile.mktemp(suffix=".cab")
  41. m.ExtractCAB(cabname)
  42. cab_and_filecount.append((cabname, len(m.ModuleFiles)))
  43. m.CloseModule()
  44. m.CloseDatabase(True)
  45. m.CloseLog()
  46. # Step 2: Add CAB files
  47. i = msilib.MakeInstaller()
  48. db = i.OpenDatabase(msi, win32com.client.constants.msiOpenDatabaseModeTransact)
  49. v = db.OpenView("SELECT LastSequence FROM Media")
  50. v.Execute(None)
  51. maxmedia = -1
  52. while 1:
  53. r = v.Fetch()
  54. if not r: break
  55. seq = r.IntegerData(1)
  56. if seq > maxmedia:
  57. maxmedia = seq
  58. print "Start of Media", maxmedia
  59. for cabname, count in cab_and_filecount:
  60. stream = "merged%d" % maxmedia
  61. msilib.add_data(db, "Media",
  62. [(maxmedia+1, maxmedia+count, None, "#"+stream, None, None)])
  63. msilib.add_stream(db, stream, cabname)
  64. os.unlink(cabname)
  65. maxmedia += count
  66. # The merge module sets ALLUSERS to 1 in the property table.
  67. # This is undesired; delete that
  68. v = db.OpenView("DELETE FROM Property WHERE Property='ALLUSERS'")
  69. v.Execute(None)
  70. v.Close()
  71. db.Commit()
  72. merge(msi, "SharedCRT", "TARGETDIR", modules)
  73. # certname (from config.py) should be (a substring of)
  74. # the certificate subject, e.g. "Python Software Foundation"
  75. if certname:
  76. os.system('signtool sign /n "%s" /t http://timestamp.verisign.com/scripts/timestamp.dll %s' % (certname, msi))