Link to home
Start Free TrialLog in
Avatar of wayy2be
wayy2be

asked on

Python code examples on how to read Windows Registry

I need to write a Python script that will read and display to the screen or a file specified keys of the Windows Registry. How can I do this?
Avatar of pepr
pepr

There is the standard module called _winreg in Python -- see http://docs.python.org/library/_winreg.html
Basically, it is a wrapper around the Windows API.  This way it should be used as Windows OS says it should be used.  If you have (say) a C++ code, you can easily rewrite it to Python.  Fortunately, the resulting code is much more brief.  Of course, you can write your own function that takes arguments as you need, and then it calls the _winreg functions.

See the sample below that reads the MDAC version from the registry.  It prints the following on my computer:

C:\tmp\___python\wayy2be\Q_26622655>python a.py
6.1.7600.16385
import _winreg

def getMDACversion():
    
    # Open the key and return the handle object.
    hKey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 
                          "Software\\Microsoft\\DataAccess")
                          
    # Read the value.                      
    result = _winreg.QueryValueEx(hKey, "FullInstallVer")

    # Return only the value from the resulting tuple (value, type_as_int).
    return result[0]


print getMDACversion()

Open in new window

Sorry, I forgot to close the handle (the _winreg.CloseKey(hKey)).  See the corrected sample below.
import _winreg

def getMDACversion():
    
    # Open the key and return the handle object.
    hKey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 
                          "Software\\Microsoft\\DataAccess")
                          
    # Read the value.                      
    result = _winreg.QueryValueEx(hKey, "FullInstallVer")

    # Close the handle object.
    _winreg.CloseKey(hKey)

    # Return only the value from the resulting tuple (value, type_as_int).
    return result[0]


print getMDACversion()

Open in new window

Avatar of wayy2be

ASKER

Thanks for the response. I am trying to have this script read the registry and scan the keys and print them. I need the script to read and cycle though several values, each are numbered like url1, url2 etc.  

# Read the value.                      
    result = _winreg.QueryValueEx(hKey, "FullInstallVer")

I can change the above to read the key url1, but how can I modify it to use a wildcard since we dont know how many keys will be there?
Do you know where the values are located?  If yes, you can get more details about the key via the _winreg.QueryInfoKey() and access the values from inside via EnumValue(). See the snippet below.  It prints the following info on my computer (long url values shortened for brevity here):

C:\tmp\_Python\wayy2be\Q_26622655.html>python b.py
0 4
('url1', u'http://websearch.ask.com/redirect?client=...1FD75CEEBF33', 1)
('url2', u'http://partners.microsoft.com/', 1)
('url3', u'http://www.google.cz/', 1)
('url4', u'http://pctuning.tyden.cz/navody/upravy...-lets_dance_22?start=5', 1)
import _winreg

def printCurrentUserIETypedURLs():
    
    # Open the key and return the handle object.
    hKey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, 
                           r'Software\Microsoft\Internet Explorer\TypedURLs')
                          #^ notice the 'r' here -- then backslashes need not 
                          #  to be doubled
                              
    # Get the information about the key.
    subkeyCnt, valuesCnt, modtime = _winreg.QueryInfoKey(hKey)
    print subkeyCnt, valuesCnt
    
    # Retrieve the value tuples (name, value, type).
    for n in xrange(valuesCnt):
        print _winreg.EnumValue(hKey, n)
        
    # Close the handle object.
    _winreg.CloseKey(hKey)


printCurrentUserIETypedURLs()

Open in new window

Try the above sample. Then you should specify your needs in more details.
Avatar of wayy2be

ASKER

That works, thanks. But how do I get the data when there are several user profiles on the box?  How can I make the script run through and list the data for each user? As  far as the code above can you explain how it works?  I am trying to learn Python.  Thanks for your great help!
Well, the work with the registry is Windows specific and it is rather heavy handed with respect to how it could be implemented in Python. The Windows Registry consists of several trees.  Their roots are named with the well known identifiers (like HKEY_CURRENT_USER).  That tree identification is passed to OpenKey() as the first argument.  The HKEY_CURRENT_USER points to one of the subtrees of the tree HKEY_USERS.  This way, you want to process the users from inside that tree.  See http://technet.microsoft.com/en-us/library/cc976337.aspx for details.  The users are assigned so called Security ID that represents them.  When displayed as a string they look like "S-1-5-21-1000062535-2000000004-1488888878-1554".  If you find shorter SID's, they are probably related to system parts that may behave as users sometimes.

Run regedit program to look at your registry.

The
for n in xrange(valuesCnt):

Open in new window

is a for loop that is not typical for Python.  Rather, it is typical for C or C-family languages.  Here it generates a sequence 0, 1, ..., valuesCnt-1.  That value is assigned to the n variable.

The
_winreg.EnumValue(hKey, n)

Open in new window

returns tuple for the value at the index.  (Again, this is not typical name and behaviour for the Python.  It comes directly from the Windows OS kernel.)  The number of values was earlier found via the
_winreg.QueryInfoKey(hKey)

Open in new window

.
Bad typesetting experiment.  Think about the "code" as about inlines in the above text.
Avatar of wayy2be

ASKER

I think I am missing it, especially the part where I can make the script display the data for each SID under that key....
OK. Let's do it in steps.  Firstly, here is the modification (also function name changed).  Run the regedit.exe, unfold the HKEY_USERS and copy your SID to the argument of the function call below.  It should do the same thing that the above script for HKEY_CURRENT_USER.  Notice how the key in the registry is written in a string.  The earlier

HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\TypedURLs

can be written in my case also as (there are decimal numerals instead of the x'es below)

HKEY_USERS\S-1-5-21-1xxxxxxxx5-2xxxxxxxx4-1xxxxxxxx8-1154\Software\Microsoft\Internet Explorer\TypedURLs

From that point of view, you can pass the SID (S-1-5-21-1xxxxxxxx5-2xxxxxxxx4-1xxxxxxxx8-1154) to the function and concatenate it with the '\Software\Microsoft\Internet Explorer\TypedURLs'.  The HKEY_USERS is a kind of concatenaded by the .OpenKey() method.

Try to understand that.  I will post soon the further step.
import _winreg

def theUserSID_IETypedURLs(sid):
    
    # Open the IE typed URLs for the sid and return the handle object.
    hKey = _winreg.OpenKey(_winreg.HKEY_USERS, 
                    sid + r'\Software\Microsoft\Internet Explorer\TypedURLs')
                              
    # Get the information about the key.
    subkeyCnt, valuesCnt, modtime = _winreg.QueryInfoKey(hKey)
    print subkeyCnt, valuesCnt
    
    # Retrieve the value tuples (name, value, type).
    for n in xrange(valuesCnt):
        print _winreg.EnumValue(hKey, n)
        
    # Close the handle object.
    _winreg.CloseKey(hKey)


theUserSID_IETypedURLs('S-1-5-21-1xxxxxxxx5-2xxxxxxxx4-1xxxxxxxx8-1154')

Open in new window

Now, let's retrieve the subkeys from the HKEY_USERS.  Not all of them are related to the users.
(sorry, badly attached code)
import _winreg

def usersSubkeys():
    hKey = _winreg.OpenKey(_winreg.HKEY_USERS, '')
    subkeyCnt, valuesCnt, modtime = _winreg.QueryInfoKey(hKey)

    # Retrieve the subkeys.
    for n in xrange(subkeyCnt):
        print _winreg.EnumKey(hKey, n)
        
    _winreg.CloseKey(hKey)


usersSubkeys()

Open in new window

Now the code that searches the URLs in all subkeys of the HKEY_USERS.  Not all subkeys are related to the users.  This means that they probably do not contain the urls.  The code below solves that via capturing the exception and throwing another.

The code below introduces also what is called a "generator function" in Python.  The function can be used for example in for loops and its usage behaves as generator of a sequence (each time one item).  The yield command instead of the return command is used inside the body of the function.

See below.  The userSIDs() actually does not return only the user's SIDs.  It returns also the other subkeys -- it is basically the same as the code in the upper example.  The difference is that it uses the yield instead of the print command.  Then it can be called in the for loop as here:

for sid in userSIDs():
    print sid

The theUserSID_IETypedURLs() was also modified to get the earlier behaviour.  Study the code and ask what are you interested in.

import _winreg

def theUserSID_IETypedURLs(sid):
    
    # Open the IE typed URLs for the sid and return the handle object. The list
    # of the URLs may not be present.  Try it and throw the StopIteration early
    # if no URL is there.
    try: 
        hKey = _winreg.OpenKey(_winreg.HKEY_USERS, 
                    sid + r'\Software\Microsoft\Internet Explorer\TypedURLs')
    except:
        raise StopIteration
                                
    # Get the information about the key.
    subkeyCnt, valuesCnt, modtime = _winreg.QueryInfoKey(hKey)
    print subkeyCnt, valuesCnt
    
    # Retrieve the value tuples (name, value, type).
    for n in xrange(valuesCnt):
        yield _winreg.EnumValue(hKey, n)[1]  # yield the url's only
        
    # Close the handle object.
    _winreg.CloseKey(hKey)


def userSIDs():   # this generator function should be enhanced
    hKey = _winreg.OpenKey(_winreg.HKEY_USERS, '')
    subkeyCnt, valuesCnt, modtime = _winreg.QueryInfoKey(hKey)

    # Generate the subkeys.
    for n in xrange(subkeyCnt):
        yield _winreg.EnumKey(hKey, n)  # notice the yield instead of return
        
    _winreg.CloseKey(hKey)


for sid in userSIDs():   # here the generator is used to get the SIDs
    print sid
    for url in theUserSID_IETypedURLs(sid):
        print ' ', url

Open in new window

Avatar of wayy2be

ASKER

Please note that this question is not abandoned. I was away for holiday.

pepr:  Thank you very much for the code, I will try it today and and test it. Thanks again for being very thorough and helpful in helping me understand the code and processes.
No problem :)
Avatar of wayy2be

ASKER

pepr,

That works great!  Thank you. I am learning alot via this exercise!  Is there a way to covert the sid to the actual user name and what type of account it is (admin or regular user, local group membership etc)?

What books would you recommend I use to get really good at Python, I really enjoy it.

Thanks
ASKER CERTIFIED SOLUTION
Avatar of pepr
pepr

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of wayy2be

ASKER

Actually I ran the code above without anything else and it worked very well!
Avatar of wayy2be

ASKER

Thanks for the help and for leading me in the right direction!