101 lines
3.1 KiB
Python
101 lines
3.1 KiB
Python
# Copyright (c) 2014 Google Inc. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""
|
|
TestWin.py: a collection of helpers for testing on Windows.
|
|
"""
|
|
|
|
import errno
|
|
import os
|
|
import re
|
|
import sys
|
|
import subprocess
|
|
|
|
class Registry(object):
|
|
def _QueryBase(self, sysdir, key, value):
|
|
"""Use reg.exe to read a particular key.
|
|
|
|
While ideally we might use the win32 module, we would like gyp to be
|
|
python neutral, so for instance cygwin python lacks this module.
|
|
|
|
Arguments:
|
|
sysdir: The system subdirectory to attempt to launch reg.exe from.
|
|
key: The registry key to read from.
|
|
value: The particular value to read.
|
|
Return:
|
|
stdout from reg.exe, or None for failure.
|
|
"""
|
|
# Skip if not on Windows or Python Win32 setup issue
|
|
if sys.platform not in ('win32', 'cygwin'):
|
|
return None
|
|
# Setup params to pass to and attempt to launch reg.exe
|
|
cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'),
|
|
'query', key]
|
|
if value:
|
|
cmd.extend(['/v', value])
|
|
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
# Get the stdout from reg.exe, reading to the end so p.returncode is valid
|
|
# Note that the error text may be in [1] in some cases
|
|
text = p.communicate()[0].decode('utf-8', 'ignore')
|
|
# Check return code from reg.exe; officially 0==success and 1==error
|
|
if p.returncode:
|
|
return None
|
|
return text
|
|
|
|
def Query(self, key, value=None):
|
|
r"""Use reg.exe to read a particular key through _QueryBase.
|
|
|
|
First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If
|
|
that fails, it falls back to System32. Sysnative is available on Vista and
|
|
up and available on Windows Server 2003 and XP through KB patch 942589. Note
|
|
that Sysnative will always fail if using 64-bit python due to it being a
|
|
virtual directory and System32 will work correctly in the first place.
|
|
|
|
KB 942589 - http://support.microsoft.com/kb/942589/en-us.
|
|
|
|
Arguments:
|
|
key: The registry key.
|
|
value: The particular registry value to read (optional).
|
|
Return:
|
|
stdout from reg.exe, or None for failure.
|
|
"""
|
|
text = None
|
|
try:
|
|
text = self._QueryBase('Sysnative', key, value)
|
|
except OSError as e:
|
|
if e.errno == errno.ENOENT:
|
|
text = self._QueryBase('System32', key, value)
|
|
else:
|
|
raise
|
|
return text
|
|
|
|
def GetValue(self, key, value):
|
|
"""Use reg.exe to obtain the value of a registry key.
|
|
|
|
Args:
|
|
key: The registry key.
|
|
value: The particular registry value to read.
|
|
Return:
|
|
contents of the registry key's value, or None on failure.
|
|
"""
|
|
text = self.Query(key, value)
|
|
if not text:
|
|
return None
|
|
# Extract value.
|
|
match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text)
|
|
if not match:
|
|
return None
|
|
return match.group(1)
|
|
|
|
def KeyExists(self, key):
|
|
"""Use reg.exe to see if a key exists.
|
|
|
|
Args:
|
|
key: The registry key to check.
|
|
Return:
|
|
True if the key exists
|
|
"""
|
|
if not self.Query(key):
|
|
return False
|
|
return True
|