From 7659f5588c2ad172dca9ab262a24b55c838d2047 Mon Sep 17 00:00:00 2001 From: neEverett Date: Tue, 16 May 2017 01:42:01 +0800 Subject: [PATCH 1/5] Refresh environment variables after adding Python to PATH The current script needs you to log off and then log back on to take effect. Now it takes effect immediately by broadcasting a `WM_SETTINGCHANG` message after the change of environment variables. --- Tools/scripts/win_add2path.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Tools/scripts/win_add2path.py b/Tools/scripts/win_add2path.py index 1c9aedc5ed8dca..846cced4441eb1 100644 --- a/Tools/scripts/win_add2path.py +++ b/Tools/scripts/win_add2path.py @@ -11,6 +11,7 @@ import site import os import winreg +from ctypes import windll HKCU = winreg.HKEY_CURRENT_USER ENV = "Environment" @@ -43,9 +44,22 @@ def modify(): winreg.SetValueEx(key, PATH, 0, winreg.REG_EXPAND_SZ, envpath) return paths, envpath +def refresh_environment_variables(): + HWND_BROADCAST = 0xFFFF + WM_SETTINGCHANGE = 0x001A + SMTO_ABORTIFHUNG = 0x0002 + windll.user32.SendMessageTimeoutW( + HWND_BROADCAST, + WM_SETTINGCHANGE, + 0, + ENV, + SMTO_ABORTIFHUNG, + 1000) + def main(): paths, envpath = modify() if len(paths) > 1: + refresh_environment_variables() print("Path(s) added:") print('\n'.join(paths[1:])) else: From 6573f5c65302f08b3fef3213e2962b07b5dd691f Mon Sep 17 00:00:00 2001 From: neEverett Date: Tue, 16 May 2017 16:16:28 +0800 Subject: [PATCH 2/5] Fixed several bugs * Discard the DEFAULT "%PATH%" value. The system PATH is global to all users so adding "%PATH%" in user PATH is unnecessary. * The directory of userscripts does not exist when Python is just installed. This causes the `os.path.isdir()` to always return False. But it is very possible that the directory will be created later so keep the path added is reasonable. Thus `os.path.isdir()` check is unnecessary and is now deleted. * The script compulsively sets the type of PATH var to REG_EXPAND_SZ. Now the type remains what it is. If it's REG_SZ, the `%APPDATA%...` path will not be added while the other absolute paths are normally added. * The current script needs users to log off and then log back on to take effect. Now it takes effect immediately by broadcasting a `WM_SETTINGCHANG` message after the change of env vars. * Now displays error massages when PATH fails to load PATH values or fails to refresh env vars. --- Tools/scripts/win_add2path.py | 54 ++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/Tools/scripts/win_add2path.py b/Tools/scripts/win_add2path.py index 846cced4441eb1..8e0a6b29554f18 100644 --- a/Tools/scripts/win_add2path.py +++ b/Tools/scripts/win_add2path.py @@ -11,57 +11,65 @@ import site import os import winreg -from ctypes import windll +import ctypes +import warnings HKCU = winreg.HKEY_CURRENT_USER ENV = "Environment" PATH = "PATH" -DEFAULT = "%PATH%" def modify(): pythonpath = os.path.dirname(os.path.normpath(sys.executable)) scripts = os.path.join(pythonpath, "Scripts") appdata = os.environ["APPDATA"] - if hasattr(site, "USER_SITE"): - usersite = site.USER_SITE.replace(appdata, "%APPDATA%") - userpath = os.path.dirname(usersite) - userscripts = os.path.join(userpath, "Scripts") - else: - userscripts = None with winreg.CreateKey(HKCU, ENV) as key: try: - envpath = winreg.QueryValueEx(key, PATH)[0] - except OSError: - envpath = DEFAULT + envpath, dtype = winreg.QueryValueEx(key, PATH) + except FileNotFoundError: + envpath, dtype = "", winreg.REG_EXPAND_SZ + pass + except: + raise OSError("Failed to load PATH value") + + if hasattr(site, "USER_SITE") and dtype == winreg.REG_EXPAND_SZ: + usersite = site.USER_SITE.replace(appdata, "%APPDATA%") + userpath = os.path.dirname(usersite) + userscripts = os.path.join(userpath, "Scripts") + else: + userscripts = None - paths = [envpath] + paths = [] for path in (pythonpath, scripts, userscripts): - if path and path not in envpath and os.path.isdir(path): + if (path and path not in envpath): paths.append(path) - envpath = os.pathsep.join(paths) - winreg.SetValueEx(key, PATH, 0, winreg.REG_EXPAND_SZ, envpath) + if envpath == "": + envpath = os.pathsep.join(paths) + else: + envpath = os.pathsep.join([envpath] + paths) + winreg.SetValueEx(key, PATH, 0, dtype, envpath) return paths, envpath def refresh_environment_variables(): HWND_BROADCAST = 0xFFFF WM_SETTINGCHANGE = 0x001A SMTO_ABORTIFHUNG = 0x0002 - windll.user32.SendMessageTimeoutW( - HWND_BROADCAST, - WM_SETTINGCHANGE, - 0, - ENV, - SMTO_ABORTIFHUNG, - 1000) + if not ctypes.windll.user32.SendMessageTimeoutW( + HWND_BROADCAST, + WM_SETTINGCHANGE, + 0, + ENV, + SMTO_ABORTIFHUNG, + 1000): + raise ctypes.WinError() def main(): paths, envpath = modify() if len(paths) > 1: refresh_environment_variables() print("Path(s) added:") - print('\n'.join(paths[1:])) + print('\n'.join(paths)) else: print("No path was added") print("\nPATH is now:\n%s\n" % envpath) From cdf93f5917c43f015e341201e82d77fabe75c187 Mon Sep 17 00:00:00 2001 From: neEverett Date: Tue, 16 May 2017 16:38:51 +0800 Subject: [PATCH 3/5] add absolute path when type of PATH is REG_SZ If the type is REG_SZ, the `%APPDATA%...` path will not be added and the absolute path will be added instead. --- Tools/scripts/win_add2path.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tools/scripts/win_add2path.py b/Tools/scripts/win_add2path.py index 8e0a6b29554f18..b29a288aede591 100644 --- a/Tools/scripts/win_add2path.py +++ b/Tools/scripts/win_add2path.py @@ -36,6 +36,9 @@ def modify(): usersite = site.USER_SITE.replace(appdata, "%APPDATA%") userpath = os.path.dirname(usersite) userscripts = os.path.join(userpath, "Scripts") + elif dtype == winreg.REG_SZ: + userpath = site.USER_SITE + userscripts = os.path.join(userpath, "Scripts") else: userscripts = None From bcef92c505ad1a9b3b99788eb143fb9dd52f6f47 Mon Sep 17 00:00:00 2001 From: neEverett Date: Wed, 17 May 2017 01:10:02 +0800 Subject: [PATCH 4/5] delete unused import --- Tools/scripts/win_add2path .py | 79 ++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Tools/scripts/win_add2path .py diff --git a/Tools/scripts/win_add2path .py b/Tools/scripts/win_add2path .py new file mode 100644 index 00000000000000..29d0a22fe3f1d1 --- /dev/null +++ b/Tools/scripts/win_add2path .py @@ -0,0 +1,79 @@ +"""Add Python to the search path on Windows + +This is a simple script to add Python to the Windows search path. It +modifies the current user (HKCU) tree of the registry. + +Copyright (c) 2008 by Christian Heimes +Licensed to PSF under a Contributor Agreement. +""" + +import sys +import site +import os +import winreg +import ctypes + +HKCU = winreg.HKEY_CURRENT_USER +ENV = "Environment" +PATH = "PATH" + +def modify(): + pythonpath = os.path.dirname(os.path.normpath(sys.executable)) + scripts = os.path.join(pythonpath, "Scripts") + appdata = os.environ["APPDATA"] + + with winreg.CreateKey(HKCU, ENV) as key: + try: + envpath, dtype = winreg.QueryValueEx(key, PATH) + except FileNotFoundError: + envpath, dtype = "", winreg.REG_EXPAND_SZ + pass + except: + raise OSError("Failed to load PATH value") + + if hasattr(site, "USER_SITE") and dtype != winreg.REG_SZ: + usersite = site.USER_SITE.replace(appdata, "%APPDATA%") + userpath = os.path.dirname(usersite) + userscripts = os.path.join(userpath, "Scripts") + else: + userscripts = None + + paths = [] + for path in (pythonpath, scripts, userscripts): + if (path and path not in envpath): + paths.append(path) + + if envpath == "": + envpath = os.pathsep.join(paths) + else: + envpath = os.pathsep.join([envpath] + paths) + winreg.SetValueEx(key, PATH, 0, dtype, envpath) + return paths, envpath + +def refresh_environment_variables(): + HWND_BROADCAST = 0xFFFF + WM_SETTINGCHANGE = 0x001A + SMTO_ABORTIFHUNG = 0x0002 + if not ctypes.windll.user32.SendMessageTimeoutW( + HWND_BROADCAST, + WM_SETTINGCHANGE, + 0, + ENV, + SMTO_ABORTIFHUNG, + 1000): + raise ctypes.WinError() + +def main(): + paths, envpath = modify() + if len(paths) > 1: + print("Path(s) added:") + print('\n'.join(paths)) + refresh_environment_variables() + else: + print("No path was added") + print("\nPATH is now:\n%s\n" % envpath) + print("Expanded:") + print(winreg.ExpandEnvironmentStrings(envpath)) + +if __name__ == '__main__': + main() From c0f9dc348effc31c7f00d2828ca7ca6bf88954ed Mon Sep 17 00:00:00 2001 From: neEverett Date: Wed, 17 May 2017 01:10:40 +0800 Subject: [PATCH 5/5] Delete win_add2path .py --- Tools/scripts/win_add2path .py | 79 ---------------------------------- 1 file changed, 79 deletions(-) delete mode 100644 Tools/scripts/win_add2path .py diff --git a/Tools/scripts/win_add2path .py b/Tools/scripts/win_add2path .py deleted file mode 100644 index 29d0a22fe3f1d1..00000000000000 --- a/Tools/scripts/win_add2path .py +++ /dev/null @@ -1,79 +0,0 @@ -"""Add Python to the search path on Windows - -This is a simple script to add Python to the Windows search path. It -modifies the current user (HKCU) tree of the registry. - -Copyright (c) 2008 by Christian Heimes -Licensed to PSF under a Contributor Agreement. -""" - -import sys -import site -import os -import winreg -import ctypes - -HKCU = winreg.HKEY_CURRENT_USER -ENV = "Environment" -PATH = "PATH" - -def modify(): - pythonpath = os.path.dirname(os.path.normpath(sys.executable)) - scripts = os.path.join(pythonpath, "Scripts") - appdata = os.environ["APPDATA"] - - with winreg.CreateKey(HKCU, ENV) as key: - try: - envpath, dtype = winreg.QueryValueEx(key, PATH) - except FileNotFoundError: - envpath, dtype = "", winreg.REG_EXPAND_SZ - pass - except: - raise OSError("Failed to load PATH value") - - if hasattr(site, "USER_SITE") and dtype != winreg.REG_SZ: - usersite = site.USER_SITE.replace(appdata, "%APPDATA%") - userpath = os.path.dirname(usersite) - userscripts = os.path.join(userpath, "Scripts") - else: - userscripts = None - - paths = [] - for path in (pythonpath, scripts, userscripts): - if (path and path not in envpath): - paths.append(path) - - if envpath == "": - envpath = os.pathsep.join(paths) - else: - envpath = os.pathsep.join([envpath] + paths) - winreg.SetValueEx(key, PATH, 0, dtype, envpath) - return paths, envpath - -def refresh_environment_variables(): - HWND_BROADCAST = 0xFFFF - WM_SETTINGCHANGE = 0x001A - SMTO_ABORTIFHUNG = 0x0002 - if not ctypes.windll.user32.SendMessageTimeoutW( - HWND_BROADCAST, - WM_SETTINGCHANGE, - 0, - ENV, - SMTO_ABORTIFHUNG, - 1000): - raise ctypes.WinError() - -def main(): - paths, envpath = modify() - if len(paths) > 1: - print("Path(s) added:") - print('\n'.join(paths)) - refresh_environment_variables() - else: - print("No path was added") - print("\nPATH is now:\n%s\n" % envpath) - print("Expanded:") - print(winreg.ExpandEnvironmentStrings(envpath)) - -if __name__ == '__main__': - main()