winutils.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #-----------------------------------------------------------------------------
  2. # Copyright (c) 2013-2021, PyInstaller Development Team.
  3. #
  4. # Distributed under the terms of the GNU General Public License (version 2
  5. # or later) with exception for distributing the bootloader.
  6. #
  7. # The full license is in the file COPYING.txt, distributed with this software.
  8. #
  9. # SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
  10. #-----------------------------------------------------------------------------
  11. """
  12. Utils for Windows platform.
  13. """
  14. __all__ = ['get_windows_dir']
  15. import os
  16. import sys
  17. from PyInstaller import compat
  18. import PyInstaller.log as logging
  19. logger = logging.getLogger(__name__)
  20. def get_windows_dir():
  21. """
  22. Return the Windows directory e.g. C:\\Windows.
  23. """
  24. # imported here to avoid circular import
  25. from PyInstaller import compat
  26. windir = compat.win32api.GetWindowsDirectory()
  27. if not windir:
  28. raise SystemExit("Error: Can not determine your Windows directory")
  29. return windir
  30. def get_system_path():
  31. """
  32. Return the required Windows system paths.
  33. """
  34. # imported here to avoid circular import
  35. from PyInstaller import compat
  36. _bpath = []
  37. sys_dir = compat.win32api.GetSystemDirectory()
  38. # Ensure C:\Windows\system32 and C:\Windows directories are
  39. # always present in PATH variable.
  40. # C:\Windows\system32 is valid even for 64bit Windows. Access do DLLs are
  41. # transparently redirected to C:\Windows\syswow64 for 64bit applactions.
  42. # http://msdn.microsoft.com/en-us/library/aa384187(v=vs.85).aspx
  43. _bpath = [sys_dir, get_windows_dir()]
  44. return _bpath
  45. def extend_system_path(paths):
  46. """
  47. Add new paths at the beginning of environment variable PATH.
  48. Some hooks might extend PATH where PyInstaller should look for dlls.
  49. """
  50. # imported here to avoid circular import
  51. from PyInstaller import compat
  52. old_PATH = compat.getenv('PATH', '')
  53. paths.append(old_PATH)
  54. new_PATH = os.pathsep.join(paths)
  55. compat.setenv('PATH', new_PATH)
  56. def import_pywin32_module(module_name):
  57. """
  58. Import and return the PyWin32 module with the passed name.
  59. When imported, the `pywintypes` and `pythoncom` modules both internally
  60. import dynamic libraries (e.g., `pywintypes.py` imports `pywintypes34.dll`
  61. under Python 3.4). The Anaconda Python distribution for Windows installs
  62. these libraries to non-standard directories, resulting in
  63. `"ImportError: No system module 'pywintypes' (pywintypes34.dll)"`
  64. exceptions. This function catches these exceptions, searches for these
  65. libraries, adds their directories to `sys.path`, and retries.
  66. Parameters
  67. ----------
  68. module_name : str
  69. Fully-qualified name of this module.
  70. Returns
  71. ----------
  72. types.ModuleType
  73. The desired module.
  74. """
  75. module = None
  76. try:
  77. module = __import__(
  78. module_name, globals={}, locals={}, fromlist=[''])
  79. except ImportError as exc:
  80. if str(exc).startswith('No system module'):
  81. # True if "sys.frozen" is currently set.
  82. is_sys_frozen = hasattr(sys, 'frozen')
  83. # Current value of "sys.frozen" if any.
  84. sys_frozen = getattr(sys, 'frozen', None)
  85. # Force PyWin32 to search "sys.path" for DLLs. By default, PyWin32
  86. # only searches "site-packages\win32\lib/", "sys.prefix", and
  87. # Windows system directories (e.g., "C:\Windows\System32"). This is
  88. # an ugly hack, but there is no other way.
  89. sys.frozen = '|_|GLYH@CK'
  90. # If isolated to a venv, the preferred site.getsitepackages()
  91. # function is unreliable. Fallback to searching "sys.path" instead.
  92. if compat.is_venv:
  93. sys_paths = sys.path
  94. else:
  95. sys_paths = compat.getsitepackages()
  96. for sys_path in sys_paths:
  97. # Absolute path of the directory containing PyWin32 DLLs.
  98. pywin32_dll_dir = os.path.join(sys_path, 'pywin32_system32')
  99. if os.path.isdir(pywin32_dll_dir):
  100. sys.path.append(pywin32_dll_dir)
  101. try:
  102. module = __import__(
  103. name=module_name, globals={}, locals={}, fromlist=[''])
  104. break
  105. except ImportError:
  106. pass
  107. # If "sys.frozen" was previously set, restore its prior value.
  108. if is_sys_frozen:
  109. sys.frozen = sys_frozen
  110. # Else, undo this hack entirely.
  111. else:
  112. del sys.frozen
  113. # If this module remains unimportable, PyWin32 is not installed. Fail.
  114. if module is None:
  115. raise
  116. return module
  117. def convert_dll_name_to_str(dll_name):
  118. """
  119. Convert dll names from 'bytes' to 'str'.
  120. Latest pefile returns type 'bytes'.
  121. :param dll_name:
  122. :return:
  123. """
  124. # imported here to avoid circular import
  125. if isinstance(dll_name, bytes):
  126. return str(dll_name, encoding='UTF-8')
  127. else:
  128. return dll_name
  129. def set_exe_checksum(exe_path):
  130. """Set executable's checksum in its metadata.
  131. This optional checksum is supposed to protect the executable against
  132. corruption but some anti-viral software have taken to flagging anything
  133. without it set correctly as malware. See issue #5579.
  134. """
  135. import pefile
  136. pe = pefile.PE(exe_path)
  137. pe.OPTIONAL_HEADER.CheckSum = pe.generate_checksum()
  138. pe.close()
  139. pe.write(exe_path)