Skip to content

Commit e812ebd

Browse files
committed
Refactored registry.py and renamed get_registry_values to get_installed_steam_games. Also improved error handling in there.
1 parent c7993f5 commit e812ebd

2 files changed

Lines changed: 45 additions & 33 deletions

File tree

resources/main.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,7 @@ def installed_games():
6161
'If this problem persists please contact support.')
6262
return
6363

64-
# TODO : Refactor and/or rename get_registry_values, and perhaps return an array of appids instead of a dictionary.
65-
# currently returns a dictionary of string appid as keys, and only values '1'. Uninstalled games in the registry are actually not returned by this function
66-
installed_appids_dict = registry.get_registry_values(os.path.join(__addon__.getSetting('steam-path'), 'registry.vdf'))
67-
# Get an Array of dictionary keys, ie of the installed games appids. TODO return an array directly from the function above.
68-
installed_appids = installed_appids_dict.keys()
64+
installed_appids = registry.get_installed_steam_apps(os.path.join(__addon__.getSetting('steam-path'), 'registry.vdf'))
6965

7066
# filter out any applications not listed as installed
7167
steam_installed_games = filter(lambda app_entry: str(app_entry['appid']) in installed_appids, steam_games_details)

resources/registry.py

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@
44

55
import os
66
import xbmc
7-
from util import log
7+
from util import *
88

99
if os.name == 'nt':
1010
import _winreg
1111

1212

1313
# https://github.com/lutris/lutris/blob/master/lutris/util/steam.py
1414
def vdf_parse(steam_config_file, config):
15-
"""Parse a Steam config file and return the contents as a dict."""
15+
"""Parse a Steam config file and return the contents as a dict with lowercase keys.
16+
The motivation behind returning lowercase keys is that the case is not consistent between environments it seems.
17+
"""
1618
line = " "
1719
while line:
1820
try:
@@ -30,54 +32,68 @@ def vdf_parse(steam_config_file, config):
3032

3133
line_elements = line.strip().split("\"")
3234
if len(line_elements) == 3:
33-
key = line_elements[1]
35+
key = line_elements[1].lower()
3436
steam_config_file.readline() # skip '{'
3537
config[key] = vdf_parse(steam_config_file, {})
3638
else:
3739
try:
38-
config[line_elements[1]] = line_elements[3]
40+
config[line_elements[1].lower()] = line_elements[3]
3941
except IndexError:
4042
log('Malformed config file: {}'.format(line), xbmc.LOGERROR)
4143
return config
4244

4345

44-
def is_installed(app_id):
45-
app = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, "Software\\Valve\\Steam\\Apps\\" + app_id)
46+
def is_installed_win(app_id):
47+
"""
48+
Gets whether an app with the given app id is installed, on Windows
49+
:param app_id: app_id to check
50+
:return: True if the app is installed, false otherwise
51+
"""
4652
try:
47-
i = 0
48-
while 1:
53+
app = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, "Software\\Valve\\Steam\\Apps\\" + app_id)
54+
print(_winreg.QueryInfoKey(app)[1])
55+
for i in range(_winreg.QueryInfoKey(app)[1]):
4956
name, value, type = _winreg.EnumValue(app, i)
5057
if name == "Installed":
51-
return value
52-
i += 1
58+
return value == 1
59+
5360
except WindowsError:
54-
return None
61+
pass
62+
# Sometimes the key "Installed" does not exist, and we get out of the loop without returning anything,so we return False at the end of the function
63+
return False
5564

5665

57-
def get_registry_values(registry_path):
58-
app_dict = {}
66+
def get_installed_steam_apps(registry_path):
67+
"""
68+
Obtains the steam games/apps installed on the computer.
69+
:param registry_path: Path to the registry.vdf file
70+
:return: an array of appids that are installed.
71+
"""
72+
installed_apps = []
5973

6074
if os.name == 'nt':
61-
apps = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, "Software\\Valve\\Steam\\Apps")
6275
try:
63-
i = 0
64-
while True:
76+
apps = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, "Software\\Valve\\Steam\\Apps")
77+
print(_winreg.QueryInfoKey(apps)[0])
78+
for i in range(_winreg.QueryInfoKey(apps)[0]):
6579
app_id = _winreg.EnumKey(apps, i)
66-
# print(app_id)
67-
installed = is_installed(app_id)
68-
i += 1
69-
if installed:
70-
app_dict[app_id] = installed
80+
if is_installed_win(app_id):
81+
installed_apps.append(app_id)
7182

72-
except WindowsError:
83+
except WindowsError as e:
84+
show_error(e, "Error while reading Windows registry")
7385
pass
7486
else:
7587
with open(registry_path, 'r') as file:
76-
vdf = vdf_parse(file, {})
77-
apps = vdf['Registry']['HKCU']['Software']['Valve']['Steam']['Apps']
88+
try:
89+
vdf = vdf_parse(file, {})
90+
apps = vdf['registry']['hkcu']['software']['valve']['steam']['apps']
7891

79-
# apparently case of 'installed' differs depending on ... ?
80-
# i'm sure if i were a python programmer this would look nicer
81-
app_dict = dict((k, v) for (k, v) in apps.iteritems() if ({k.lower(): v for k, v in v.items()}.get('installed', '0') == '1'))
92+
# apparently case of 'installed' differs depending on ... ?
93+
# We create a list of the apps that have a "installed" key equal to "1".
94+
installed_apps = [appid for (appid, information) in apps.items() if (information.get('installed', '0') == '1')]
95+
except KeyError as e:
96+
show_error(e, "Error finding the values from registry.vdf")
97+
pass
8298

83-
return app_dict
99+
return installed_apps

0 commit comments

Comments
 (0)