mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #45763 from twangboy/win_fix_path_rehash
Fix rehash function in win_path.py
This commit is contained in:
commit
edcb64de76
5 changed files with 97 additions and 51 deletions
|
@ -29,8 +29,8 @@ Values/Entries are name/data pairs. There can be many values in a key. The
|
|||
# When production windows installer is using Python 3, Python 2 code can be removed
|
||||
|
||||
# Import _future_ python libs first & before any other code
|
||||
from __future__ import absolute_import
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
# Import python libs
|
||||
import sys
|
||||
import logging
|
||||
|
@ -38,7 +38,6 @@ from salt.ext.six.moves import range # pylint: disable=W0622,import-error
|
|||
|
||||
# Import third party libs
|
||||
try:
|
||||
import win32gui
|
||||
import win32api
|
||||
import win32con
|
||||
import pywintypes
|
||||
|
@ -48,6 +47,7 @@ except ImportError:
|
|||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
import salt.utils.win_functions
|
||||
from salt.exceptions import CommandExecutionError
|
||||
|
||||
PY2 = sys.version_info[0] == 2
|
||||
|
@ -68,7 +68,7 @@ def __virtual__():
|
|||
if not HAS_WINDOWS_MODULES:
|
||||
return (False, 'reg execution module failed to load: '
|
||||
'One of the following libraries did not load: '
|
||||
+ 'win32gui, win32con, win32api')
|
||||
'win32con, win32api, pywintypes')
|
||||
|
||||
return __virtualname__
|
||||
|
||||
|
@ -193,11 +193,7 @@ def broadcast_change():
|
|||
|
||||
salt '*' reg.broadcast_change
|
||||
'''
|
||||
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms644952(v=vs.85).aspx
|
||||
_, res = win32gui.SendMessageTimeout(
|
||||
win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 0,
|
||||
win32con.SMTO_ABORTIFHUNG, 5000)
|
||||
return not bool(res)
|
||||
return salt.utils.win_functions.broadcast_setting_change('Environment')
|
||||
|
||||
|
||||
def list_keys(hive, key=None, use_32bit_registry=False):
|
||||
|
|
|
@ -16,14 +16,13 @@ from salt.ext.six.moves import map
|
|||
|
||||
# Third party libs
|
||||
try:
|
||||
from win32con import HWND_BROADCAST, WM_SETTINGCHANGE
|
||||
from win32api import SendMessage
|
||||
HAS_WIN32 = True
|
||||
except ImportError:
|
||||
HAS_WIN32 = False
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
import salt.utils.win_functions
|
||||
|
||||
# Settings
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -47,7 +46,15 @@ def _normalize_dir(string):
|
|||
|
||||
def rehash():
|
||||
'''
|
||||
Send a WM_SETTINGCHANGE Broadcast to Windows to refresh the Environment variables
|
||||
Send a WM_SETTINGCHANGE Broadcast to Windows to refresh the Environment
|
||||
variables for new processes.
|
||||
|
||||
.. note::
|
||||
This will only affect new processes that aren't launched by services. To
|
||||
apply changes to the path to services, the host must be restarted. The
|
||||
``salt-minion``, if running as a service, will not see changes to the
|
||||
environment until the system is restarted. See
|
||||
`MSDN Documentation <https://support.microsoft.com/en-us/help/821761/changes-that-you-make-to-environment-variables-do-not-affect-services>`_
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -55,7 +62,7 @@ def rehash():
|
|||
|
||||
salt '*' win_path.rehash
|
||||
'''
|
||||
return bool(SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 'Environment'))
|
||||
return salt.utils.win_functions.broadcast_setting_change('Environment')
|
||||
|
||||
|
||||
def get_path():
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
Various functions to be used by windows during start up and to monkey patch
|
||||
missing functions in other modules
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
import platform
|
||||
import re
|
||||
import ctypes
|
||||
|
||||
# Import Salt Libs
|
||||
from salt.exceptions import CommandExecutionError
|
||||
|
@ -17,6 +18,7 @@ try:
|
|||
import win32api
|
||||
import win32net
|
||||
import win32security
|
||||
from win32con import HWND_BROADCAST, WM_SETTINGCHANGE, SMTO_ABORTIFHUNG
|
||||
HAS_WIN32 = True
|
||||
except ImportError:
|
||||
HAS_WIN32 = False
|
||||
|
@ -210,3 +212,72 @@ def escape_for_cmd_exe(arg):
|
|||
return meta_map[char]
|
||||
|
||||
return meta_re.sub(escape_meta_chars, arg)
|
||||
|
||||
|
||||
def broadcast_setting_change(message='Environment'):
|
||||
'''
|
||||
Send a WM_SETTINGCHANGE Broadcast to all Windows
|
||||
|
||||
Args:
|
||||
|
||||
message (str):
|
||||
A string value representing the portion of the system that has been
|
||||
updated and needs to be refreshed. Default is ``Environment``. These
|
||||
are some common values:
|
||||
|
||||
- "Environment" : to effect a change in the environment variables
|
||||
- "intl" : to effect a change in locale settings
|
||||
- "Policy" : to effect a change in Group Policy Settings
|
||||
- a leaf node in the registry
|
||||
- the name of a section in the ``Win.ini`` file
|
||||
|
||||
See lParam within msdn docs for
|
||||
`WM_SETTINGCHANGE <https://msdn.microsoft.com/en-us/library/ms725497%28VS.85%29.aspx>`_
|
||||
for more information on Broadcasting Messages.
|
||||
|
||||
See GWL_WNDPROC within msdn docs for
|
||||
`SetWindowLong <https://msdn.microsoft.com/en-us/library/windows/desktop/ms633591(v=vs.85).aspx>`_
|
||||
for information on how to retrieve those messages.
|
||||
|
||||
.. note::
|
||||
This will only affect new processes that aren't launched by services. To
|
||||
apply changes to the path or registry to services, the host must be
|
||||
restarted. The ``salt-minion``, if running as a service, will not see
|
||||
changes to the environment until the system is restarted. Services
|
||||
inherit their environment from ``services.exe`` which does not respond
|
||||
to messaging events. See
|
||||
`MSDN Documentation <https://support.microsoft.com/en-us/help/821761/changes-that-you-make-to-environment-variables-do-not-affect-services>`_
|
||||
for more information.
|
||||
|
||||
CLI Example:
|
||||
|
||||
... code-block:: python
|
||||
|
||||
import salt.utils.win_functions
|
||||
salt.utils.win_functions.broadcast_setting_change('Environment')
|
||||
'''
|
||||
# Listen for messages sent by this would involve working with the
|
||||
# SetWindowLong function. This can be accessed via win32gui or through
|
||||
# ctypes. You can find examples on how to do this by searching for
|
||||
# `Accessing WGL_WNDPROC` on the internet. Here are some examples of how
|
||||
# this might work:
|
||||
#
|
||||
# # using win32gui
|
||||
# import win32con
|
||||
# import win32gui
|
||||
# old_function = win32gui.SetWindowLong(window_handle, win32con.GWL_WNDPROC, new_function)
|
||||
#
|
||||
# # using ctypes
|
||||
# import ctypes
|
||||
# import win32con
|
||||
# from ctypes import c_long, c_int
|
||||
# user32 = ctypes.WinDLL('user32', use_last_error=True)
|
||||
# WndProcType = ctypes.WINFUNCTYPE(c_int, c_long, c_int, c_int)
|
||||
# new_function = WndProcType
|
||||
# old_function = user32.SetWindowLongW(window_handle, win32con.GWL_WNDPROC, new_function)
|
||||
broadcast_message = ctypes.create_unicode_buffer(message)
|
||||
user32 = ctypes.WinDLL('user32', use_last_error=True)
|
||||
result = user32.SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
|
||||
broadcast_message, SMTO_ABORTIFHUNG,
|
||||
5000, 0)
|
||||
return result == 1
|
||||
|
|
|
@ -20,49 +20,13 @@ from tests.support.mock import (
|
|||
import salt.modules.win_path as win_path
|
||||
|
||||
|
||||
class MockWin32API(object):
|
||||
'''
|
||||
Mock class for win32api
|
||||
'''
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def SendMessage(*args):
|
||||
'''
|
||||
Mock method for SendMessage
|
||||
'''
|
||||
return [args[0]]
|
||||
|
||||
|
||||
class MockWin32Con(object):
|
||||
'''
|
||||
Mock class for win32con
|
||||
'''
|
||||
HWND_BROADCAST = 1
|
||||
WM_SETTINGCHANGE = 1
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class WinPathTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
Test cases for salt.modules.win_path
|
||||
'''
|
||||
def setup_loader_modules(self):
|
||||
return {win_path: {'win32api': MockWin32API,
|
||||
'win32con': MockWin32Con,
|
||||
'SendMessage': MagicMock,
|
||||
'HWND_BROADCAST': MagicMock,
|
||||
'WM_SETTINGCHANGE': MagicMock}}
|
||||
|
||||
def test_rehash(self):
|
||||
'''
|
||||
Test to rehash the Environment variables
|
||||
'''
|
||||
self.assertTrue(win_path.rehash())
|
||||
return {win_path: {}}
|
||||
|
||||
def test_get_path(self):
|
||||
'''
|
||||
|
|
|
@ -12,6 +12,7 @@ from tests.support.mock import (
|
|||
|
||||
# Import Salt Libs
|
||||
import salt.utils.win_functions as win_functions
|
||||
import salt.utils
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
|
@ -51,3 +52,10 @@ class WinFunctionsTestCase(TestCase):
|
|||
encoded = win_functions.escape_argument('C:\\Some Path\\With Spaces')
|
||||
|
||||
self.assertEqual(encoded, '^"C:\\Some Path\\With Spaces^"')
|
||||
|
||||
@skipIf(not salt.utils.is_windows(), 'WinDLL only available on Windows')
|
||||
def test_broadcast_setting_change(self):
|
||||
'''
|
||||
Test to rehash the Environment variables
|
||||
'''
|
||||
self.assertTrue(win_functions.broadcast_setting_change())
|
||||
|
|
Loading…
Add table
Reference in a new issue