msifixup.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #!/usr/bin/env python3
  2. import argparse
  3. import os
  4. import tempfile
  5. import shutil
  6. import subprocess
  7. import shlex
  8. def run(command, verbose):
  9. if verbose:
  10. sys.stdout.write("$ {}\n".format(" ".join(
  11. shlex.quote(word) for word in command)))
  12. out = subprocess.check_output(command)
  13. if verbose:
  14. sys.stdout.write("".join(
  15. "> {}\n".format(line) for line in out.splitlines()))
  16. def make_changes(msi, args):
  17. run(["msidump", "-t", msi], args.verbose)
  18. build_cmd = ["msibuild", msi]
  19. def change_table(filename):
  20. with open(filename) as fh:
  21. lines = [line.rstrip("\r\n").split("\t")
  22. for line in iter(fh.readline, "")]
  23. for line in lines[3:]:
  24. yield line
  25. with open(filename, "w") as fh:
  26. for line in lines:
  27. fh.write("\t".join(line) + "\r\n")
  28. build_cmd.extend(["-i", filename])
  29. if args.platform is not None:
  30. for line in change_table("_SummaryInformation.idt"):
  31. if line[0] == "7":
  32. line[1] = ";".join([args.platform] + line[1].split(";", 1)[1:])
  33. if args.dialog_bmp_width is not None:
  34. for line in change_table("Control.idt"):
  35. if line[9] == "WixUI_Bmp_Dialog":
  36. line[5] = args.dialog_bmp_width
  37. run(build_cmd, args.verbose)
  38. def main():
  39. parser = argparse.ArgumentParser(
  40. description='Change the platform field of an MSI installer package.')
  41. parser.add_argument("msi", help="MSI installer file.")
  42. parser.add_argument("--platform", help="Change the platform field.")
  43. parser.add_argument("--dialog-bmp-width", help="Change the width field"
  44. " in all uses of WixUI_Bmp_Dialog.")
  45. parser.add_argument("-v", "--verbose", action="store_true",
  46. help="Log what this script is doing.")
  47. parser.add_argument("-k", "--keep", action="store_true",
  48. help="Don't delete the temporary working directory.")
  49. args = parser.parse_args()
  50. msi = os.path.abspath(args.msi)
  51. msidir = os.path.dirname(msi)
  52. try:
  53. tempdir = tempfile.mkdtemp(dir=msidir)
  54. os.chdir(tempdir)
  55. make_changes(msi, args)
  56. finally:
  57. if args.keep:
  58. sys.stdout.write(
  59. "Retained temporary directory {}\n".format(tempdir))
  60. else:
  61. shutil.rmtree(tempdir)
  62. if __name__ == '__main__':
  63. main()