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