Skip to content

Commit e480311

Browse files
authored
7932 win registeries (#11)
Added back checking Unreal install in registry for Windows. Revisited the [original code](https://github.com/ue4plugins/tk-unreal/blob/6863ca47b12def732883e7418934ca6590576c9b/startup.py#L111) to make it easier to understand and maintain.
1 parent 69336bc commit e480311

File tree

1 file changed

+152
-27
lines changed

1 file changed

+152
-27
lines changed

startup.py

Lines changed: 152 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import sys
77
import pprint
88
import json
9+
import re
910

1011
import sgtk
1112
from sgtk.platform import SoftwareLauncher, SoftwareVersion, LaunchInformation
@@ -148,6 +149,7 @@ def _find_software(self):
148149
Find installed UE executable.
149150
150151
:returns: List of :class:`SoftwareVersion` instances.
152+
:raises RuntimeError: For unsupported OSes.
151153
"""
152154
self.logger.info("Finding Unreal Engine executables")
153155
sw_versions = []
@@ -161,35 +163,43 @@ def _find_software(self):
161163
elif sgtk.util.is_linux():
162164
executable_templates = self.EXECUTABLE_TEMPLATES.get("linux")
163165

164-
if executable_templates:
165-
for executable_template in executable_templates:
166-
self.logger.debug("Processing template %s.", executable_template)
167-
executable_matches = self._glob_and_match(
168-
executable_template, self.COMPONENT_REGEX_LOOKUP
169-
)
170-
# Extract all products from that executable.
171-
for (executable_path, key_dict) in executable_matches:
172-
# extract the matched keys form the key_dict (default to None if
173-
# not included)
174-
executable_version = key_dict.get("version")
175-
details = self._get_unreal_version_details(executable_path)
176-
if details and all(x in details for x in ["MajorVersion", "MinorVersion", "PatchVersion"]):
177-
executable_version = "%s.%s.%s" % (
178-
details["MajorVersion"],
179-
details["MinorVersion"],
180-
details["PatchVersion"],
181-
)
182-
sw_versions.append(
183-
SoftwareVersion(
184-
executable_version,
185-
"Unreal Engine",
186-
executable_path,
187-
os.path.join(self.disk_location, "icon_256.png"),
188-
)
189-
)
190-
else:
166+
if not executable_templates:
191167
raise RuntimeError("Unsupported platform %s" % sys.platform)
192168

169+
for executable_template in executable_templates:
170+
self.logger.debug("Processing template %s.", executable_template)
171+
executable_matches = self._glob_and_match(
172+
executable_template, self.COMPONENT_REGEX_LOOKUP
173+
)
174+
# Extract all products from that executable.
175+
for (executable_path, key_dict) in executable_matches:
176+
# extract the matched keys form the key_dict (default to None if
177+
# not included)
178+
executable_version = key_dict.get("version")
179+
details = self._get_unreal_version_details(executable_path)
180+
if details and all(x in details for x in ["MajorVersion", "MinorVersion", "PatchVersion"]):
181+
executable_version = "%s.%s.%s" % (
182+
details["MajorVersion"],
183+
details["MinorVersion"],
184+
details["PatchVersion"],
185+
)
186+
sw_versions.append(
187+
SoftwareVersion(
188+
executable_version,
189+
"Unreal Engine",
190+
executable_path,
191+
os.path.join(self.disk_location, "icon_256.png"),
192+
)
193+
)
194+
if sgtk.util.is_windows():
195+
# On Windows we also explore registry, but make sure to not add
196+
# things twice.
197+
found_paths = [sw.path for sw in sw_versions]
198+
for sw in self._find_software_from_registry():
199+
if sw.path not in found_paths:
200+
sw_versions.append(sw)
201+
found_paths.append(sw.path)
202+
193203
return sw_versions
194204

195205
def _get_unreal_version_details(self, executable_path):
@@ -208,3 +218,118 @@ def _get_unreal_version_details(self, executable_path):
208218
with open(full_path) as pf:
209219
version_details = json.load(pf)
210220
return version_details
221+
222+
def _get_unreal_version(self, executable_path):
223+
"""
224+
Return the Unreal Editor version for the given executable.
225+
226+
:returns: A potentially empty version string.
227+
"""
228+
details = self._get_unreal_version_details(executable_path)
229+
if details and all(x in details for x in ["MajorVersion", "MinorVersion", "PatchVersion"]):
230+
return "%s.%s.%s" % (
231+
details["MajorVersion"],
232+
details["MinorVersion"],
233+
details["PatchVersion"],
234+
)
235+
# Fall back on parsing the executable path
236+
# Look for ue_4.7, ue_4.7.2, etc..
237+
for part in executable_path.lower().split(os.path.sep):
238+
m = re.match(r"ue_([0-9]+(?:\.[0-9]+)*)$", part)
239+
if m:
240+
return m.group(1)
241+
return ""
242+
243+
def _get_win_executable_path(self, install_path):
244+
"""
245+
Return the Unreal Editor exe path for the given install path, if one
246+
exists.
247+
248+
Check if the executable exists on the filesystem.
249+
:returns: A string, full path to the Unreal editor executable or ``None``.
250+
"""
251+
binary_path = os.path.normpath(
252+
os.path.join(install_path, "Engine", "Binaries", "Win64")
253+
)
254+
exec_path = os.path.join(binary_path, "UE4Editor.exe")
255+
if os.path.exists(exec_path):
256+
self.logger.info("Found %s" % exec_path)
257+
return exec_path
258+
# From UE5, the exe name changed
259+
exec_path = os.path.join(binary_path, "UnrealEditor.exe")
260+
if os.path.exists(exec_path):
261+
self.logger.info("Found %s" % exec_path)
262+
return exec_path
263+
264+
self.logger.info(
265+
"Couldn't find executable in installation path %s" % install_path
266+
)
267+
return None
268+
269+
def _find_software_from_registry(self):
270+
"""
271+
Find executables in the Windows Registry.
272+
273+
:returns: List of :class:`SoftwareVersion` instances.
274+
"""
275+
self.logger.info("Detecting Unreal Engine from registry...")
276+
try:
277+
# Note: keeping this as is, without knowing why it was implemented
278+
# like that, instead of just doing import winreg
279+
import _winreg
280+
except ImportError:
281+
import winreg as _winreg
282+
283+
self.logger.debug(
284+
"Querying windows registry for key HKEY_LOCAL_MACHINE\\SOFTWARE\\EpicGames\\Unreal Engine"
285+
)
286+
base_key_name = "SOFTWARE\\EpicGames\\Unreal Engine"
287+
# find all subkeys in key HKEY_LOCAL_MACHINE\SOFTWARE\EpicGames\Unreal Engine
288+
sw_versions = []
289+
try:
290+
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, base_key_name)
291+
sub_key_count = _winreg.QueryInfoKey(key)[0]
292+
for i in range(sub_key_count):
293+
sub_key_name = _winreg.EnumKey(key, i)
294+
sub_key = _winreg.OpenKey(key, sub_key_name)
295+
values_count = _winreg.QueryInfoKey(sub_key)[1]
296+
if sub_key_name == "Builds":
297+
for j in range(values_count):
298+
value = _winreg.EnumValue(sub_key, j)[1]
299+
self.logger.info("Checking %s" % value)
300+
if value and os.path.exists(value):
301+
executable_path = self._get_win_executable_path(value)
302+
if executable_path:
303+
sw = SoftwareVersion(
304+
self._get_unreal_version(executable_path),
305+
"Unreal Engine (Dev Build)",
306+
executable_path,
307+
os.path.join(self.disk_location, "icon_256.png")
308+
)
309+
sw_versions.append(sw)
310+
else:
311+
for j in range(values_count):
312+
value_name, value, _ = _winreg.EnumValue(sub_key, j)
313+
if value_name == "InstalledDirectory":
314+
if value and os.path.exists(value):
315+
executable_path = self._get_win_executable_path(value)
316+
if executable_path:
317+
sw = SoftwareVersion(
318+
self._get_unreal_version(executable_path),
319+
"Unreal Engine",
320+
executable_path,
321+
os.path.join(self.disk_location, "icon_256.png")
322+
)
323+
sw_versions.append(sw)
324+
325+
break
326+
_winreg.CloseKey(key)
327+
except WindowsError as e:
328+
self.logger.error("Error handling key %s: %s" % (base_key_name, e))
329+
# Log the traceback in debug
330+
self.logger.debug(
331+
"Error opening key %s: %s" % (base_key_name, e),
332+
exc_info=True
333+
)
334+
335+
return sw_versions

0 commit comments

Comments
 (0)