简体   繁体   中英

Python, WMI, the registry, and strange results

I need to create a python script to go through the contents of HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall and return the DisplayName of each key.

I'm using this as a starting ground (found on another stack-overflow post)

import _winreg
import wmi

c = wmi.WMI(namespace="default").StdRegProv

result, value = c.GetStringValue (
    hDefKey=_winreg.HKEY_LOCAL_MACHINE,
    sSubKeyName="SYSTEM\ControlSet001\Services\MRxDAV",
    sValueName="ImagePath"
)
print value

That works. It returns:

\SystemRoot\system32\drivers\mrxdav.sys

However, if I change the sSubKeyName and sValueName (to valid values), it appears to be extremely flaky, returning None more often than not.

For example:

c = wmi.WMI(namespace="default").StdRegProv

result, value = c.GetStringValue (
    hDefKey=_winreg.HKEY_LOCAL_MACHINE,
    sSubKeyName="SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{0E5D76AD-A3FB-48D5-8400-8903B10317D3}",
    sValueName="DisplayName"
)
print value

This results in None being printed.

However,

result, value = c.GetStringValue (
    hDefKey=_winreg.HKEY_LOCAL_MACHINE,
    sSubKeyName="SOFTWARE\Microsoft\Windows\CurrentVersion\Installer",
    sValueName="InstallerLocation"
)
print value

Returns the correct value,

C:\Windows\SysWOW64\

If we then try:

result, value = c.GetStringValue (
    hDefKey=_winreg.HKEY_LOCAL_MACHINE,
    sSubKeyName="SOFTWARE\Microsoft\Windows\CurrentVersion\OptimalLayout",
    sValueName="LayoutFilePath"
)
print value

Returns None

I've tried raw strings and escaping the slashes, neither have worked. I've also tried the GetExpandedString() method and it behaves identically.

It appears to fail with longer sSubKeyName values, but this is just a gut feeling.

EDIT

Slightly cleaner version of the code posted by Y__

key = _winreg.OpenKey(
    _winreg.HKEY_LOCAL_MACHINE,
    "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{90140000-001F-040C-1000-0000000FF1CE}",
    0, _winreg.KEY_READ | _winreg.KEY_WOW64_64KEY)

name = _winreg.QueryValueEx(key, "DisplayName")
print name[0]

I had a look at your code and noticed that when it fails, the return code is 2 which means ERROR_FILE_NOT_FOUND (ref : http://msdn.microsoft.com/en-us/library/ms681382%28v=3Dvs.%2085%29.aspx )

And indeed, for some reason, what I see using regedit and what I see with this code snippet are inconsistent :

err_code, results = c.EnumKey (
    hDefKey=_winreg.HKEY_LOCAL_MACHINE,
    sSubKeyName="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
)
print err_code
for r in results:
    print result

I'm looking to find a proper explanation for this behavior.

Hope it helps,

Best

EDIT

I think that I've found the culprit thanks to this post ( http://mail.python.org/pipermail/python-win32/2009-February/008865.html ).

So if you use the Python API to open the key you may fetch your data as needed. Here is a small (ugly) code that should do the trick :

key = _winreg.OpenKey(
    _winreg.HKEY_LOCAL_MACHINE, 
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{0E5D76AD-A3FB-48D5-8400-8903B10317D3}" ,
     0,
    _winreg.KEY_READ | _winreg.KEY_WOW64_64KEY

i = 0
while True:
    try:
        name, val, key_type = _winreg.EnumValue(key, i)
        if name == "DisplayName":
            print "%s => %s" % (name, val)
        except:
            # No more indices
            break
        i += 1

Additional reference : http://msdn.microsoft.com/en-us/library/aa384129(v=VS.85).aspx

EDIT 2

Following your comment, here is a code snippet that should do what you want :

import _winreg

def getKeys(hKey, sSubKey):
    with _winreg.OpenKey(hKey, sSubKey, 0, _winreg.KEY_READ | _winreg.KEY_WOW64_64KEY)     as key:
        idx = 0
        while True:
            try:
                yield _winreg.EnumKey(key, idx)
            except:
                # No more indices
                break
            idx += 1

hKey = _winreg.HKEY_LOCAL_MACHINE
sSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
for keyName in getKeys(hKey, sSubKey):
    with _winreg.OpenKey(hKey, "\\".join([sSubKey, keyName]) , 0, _winreg.KEY_READ |     _winreg.KEY_WOW64_64KEY) as key:
        i = 0
        while True:
            try:
                name, val, key_type = _winreg.EnumValue(key, i)
                if name == "DisplayName":
                    print "%s\\%s => %s" % (keyName, name, val)
                    break
            except:
                break

            i += 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM