swc-windows-installer.py: Search ProgramW6432 and ProgramFiles(x86)
authorW. Trevor King <wking@tremily.us>
Wed, 9 Jul 2014 23:42:20 +0000 (16:42 -0700)
committerW. Trevor King <wking@tremily.us>
Wed, 9 Jul 2014 23:54:08 +0000 (16:54 -0700)
It turns out that the 'ProgramFiles' environment variable is set
differently depending on the architecture of process in question.  To
always get the 32-bit x86 version, you should use 'ProgramFiles(x86)'
[1].  To always get the 64-bit amd64 version, you should use
'ProgramW6432' [2].

To be safe, and support both 32- and 64-bit Windows installs, just
search everything that could be relevant.  Prefer 64-bit locations
(when we have any).

[1]: http://technet.microsoft.com/en-us/library/cc749104%28v=ws.10%29.aspx
     Recognized Environment Variables
     ...
     CSIDL_PROGRAM_FILES  Version 5.0. The Program Files folder.
                          A typical path is C:\Program Files.
     ...
     PROGRAMFILES         Same as CSIDL_PROGRAM_FILES.
     PROGRAMFILES(X86)    Refers to the C:\Program Files (x86) folder on
                          64-bit systems.

[2]: http://msdn.microsoft.com/en-us/library/windows/desktop/aa384274%28v=vs.85%29.aspx#Environment_Variables
     WOW64 Implementation Details
     ...
     64-bit process:
        ProgramFiles=%ProgramFiles%
        ProgramW6432=%ProgramFiles%
     32-bit process:
        ProgramFiles=%ProgramFiles(x86)%
        ProgramW6432=%ProgramFiles%

     The ProgramW6432 and CommonProgramW6432 environment variables
     were added starting with Windows 7 and Windows Server 2008 R2.

swc-windows-installer.py

index ff0423c8cab6500a4a2eaebed26f7eb6687ecac2..0e2077d5485065aa21714c67a0df591df3e9f38e 100755 (executable)
@@ -197,15 +197,19 @@ def create_nosetests_entry_point(python_scripts_directory):
 def get_r_bin_directory():
     """Locate the R bin directory (if R is installed
     """
-    pf = os.environ.get('ProgramFiles', r'c:\Program Files')
-    bin_glob = os.path.join(pf, 'R', 'R-[0-9]*.[0-9]*.[0-9]*', 'bin')
     version_re = re.compile('^R-(\d+)[.](\d+)[.](\d+)$')
     paths = {}
-    for path in glob.glob(bin_glob):
-        version_dir = os.path.basename(os.path.dirname(path))
-        version_match = version_re.match(version_dir)
-        if version_match:
-            paths[version_match.groups()] = path
+    for pf in [
+            os.environ.get('ProgramW6432', r'c:\Program Files'),
+            os.environ.get('ProgramFiles', r'c:\Program Files'),
+            os.environ.get('ProgramFiles(x86)', r'c:\Program Files(x86)'),
+            ]:
+        bin_glob = os.path.join(pf, 'R', 'R-[0-9]*.[0-9]*.[0-9]*', 'bin')
+        for path in glob.glob(bin_glob):
+            version_dir = os.path.basename(os.path.dirname(path))
+            version_match = version_re.match(version_dir)
+            if version_match and version_match.groups() not in paths:
+                paths[version_match.groups()] = path
     if not paths:
         LOG.info('no R installation found under {}'.format(pf))
         return