diff win32.py @ 95:6c2997616bdf

Added a search for the location of the executable for Popen on Win32 This _really_ should be done by the Win32 API.
author Oleg Oshmyan <chortos@inbox.lv>
date Mon, 28 Feb 2011 21:36:57 +0000
parents c62c9bfd614a
children 6bb59a011bcb
line wrap: on
line diff
--- a/win32.py	Mon Feb 28 21:35:25 2011 +0000
+++ b/win32.py	Mon Feb 28 21:36:57 2011 +0000
@@ -8,8 +8,12 @@
 from ctypes import *
 from ctypes.wintypes import *
 from msvcrt import getch as pause
-from subprocess import Popen
-import sys
+import os, subprocess, sys
+
+try:
+	from _winreg import *
+except ImportError:
+	from winreg import *
 
 try:
 	from testcases import clock
@@ -46,6 +50,43 @@
 __all__ = 'call', 'kill', 'terminate', 'pause', 'clock'
 
 
+from functools import wraps
+pathext = [''] + os.environ['PATHEXT'].split(';')
+@wraps(subprocess.Popen)
+def Popen(cmdline, *args, **kwargs):
+	try:
+		return subprocess.Popen(cmdline, *args, **kwargs)
+	except WindowsError:
+		for ext in pathext:
+			path = cmdline[0] + ext
+			newcmdline = type(cmdline)((path,)) + cmdline[1:]
+			try:
+				return subprocess.Popen(newcmdline, *args, **kwargs)
+			except WindowsError:
+				pass
+			for branch in HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE:
+				try:
+					path = (R'SOFTWARE\Microsoft\Windows\CurrentVersion'
+					        R'\App Paths\%s%s' % (cmdline[0], ext))
+					path = QueryValue(branch, path)
+					break
+				except WindowsError:
+					pass
+			else:
+				continue
+			if path[0] == '"' == path[-1]:
+				path = path[1:-1]
+			newcmdline = type(cmdline)((path,)) + cmdline[1:]
+			try:
+				return subprocess.Popen(newcmdline, *args, **kwargs)
+			except WindowsError:
+				pass
+		# I'd like to transparently re-raise the exception generated
+		# on the very first try, but syntax differences preclude me from
+		# doing so in Python 2 and it can't be done at all in Python 3
+		raise
+
+
 # Automatically convert _subprocess handle objects into low-level HANDLEs
 # and replicate their functionality for our own use
 try: