Hi all, I have a puzzle for you today. I am trying to get the ArcGIS Pro install folder from Python. I am open to suggestions on how to accomplish this task, but the following approach should work (and works for me with Desktop, although I usually use os.environ["AGSDESKTOPJAVA"] instead).
Here is my attempt:
D:\Users\jwpowell>C:\Python27\ArcGIS10.4\python.exe
Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import _winreg
>>> with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
... r"SOFTWARE\ESRI\ArcGISPro") as key:
... pro_path = _winreg.QueryValueEx(key, "InstallDir")[0]
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
WindowsError: [Error 2] The system cannot find the file specified
And yet, I can see this key with reg query fine:
D:\Users\jwpowell>reg query HKLM\SOFTWARE\ESRI\ArcGISPro /v InstallDir
HKEY_LOCAL_MACHINE\SOFTWARE\ESRI\ArcGISPro
InstallDir REG_SZ C:\ArcGIS\Pro\
See, it works in Desktop.
>>> with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
... r"SOFTWARE\WOW6432Node\ESRI\ArcGIS") as key:
... dt_path = _winreg.QueryValueEx(key, "InstallDir")[0]
...
>>> dt_path
u'C:\\Program Files (x86)\\Common Files\\ArcGIS\\'
Is this a x64/x32 thing?
Solved! Go to Solution.
If I run your code, or equivalent code, from Pro Python installation; it works fine. I think the issue is that you are using a 32-bit Python interpreter to access the 64-bit space in the registry. The following should point you in the right direction: Change 64bit Registry from 32bit Python - Stack Overflow
D'oh just saw you don't want to use arcpy.GetInstallInfo()['InstallDir']
you can cheat... a demo using spyder as the python ide
import sys
src = [i for i in sys.path if 'spyder' in i]
Then it gives you the source for Pro since the distribution of spyder is buried within... do the split, join thing or just read it. Works with any ide installed within your conda distribution (ie pythonwin, if installed that way)
Too lazy to figure out registry stuff. But you probably don't have the luxury of local installs I bet
If I run your code, or equivalent code, from Pro Python installation; it works fine. I think the issue is that you are using a 32-bit Python interpreter to access the 64-bit space in the registry. The following should point you in the right direction: Change 64bit Registry from 32bit Python - Stack Overflow
Support for Joshua - and there's others who had that issue with 32bit: Python winreg looping through sub-keys - Stack Overflow
Here is another cool one from the depths of esri's own code
import os
import sys
d = os.path.abspath(os.path.join(sys.prefix, '..', '..', '..'))
#
# Which returns .... 'C:\\ArcPro\\bin' .... where I installed my ArcGIS PRO
but again, that has to be done with an IDE controlled by the conda distribution (Spyder in my case)
And from ...Jupyter QtConsole... so at least two IDEs bundled by esri for working with ArcGIS Pro can find it, as would be expected
Now if you are using python 3, _winreg is now winreg and this also works for my installation
import winreg
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
... r"SOFTWARE\ESRI\ArcGISPro") as key:
pro_path = winreg.QueryValueEx(key, "InstallDir")[0]
pro_path
Out[4]: 'C:\\ArcPro\\'
Read the fine manual, right Joshua?
35.3. _winreg — Windows registry access — Python 2.7.13 documentation
Accessing an Alternate Registry View (Windows)
import _winreg
with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
r"SOFTWARE\ESRI\ArcGISPro",
0,
_winreg.KEY_READ | _winreg.KEY_WOW64_64KEY
) as key:
pro_path = _winreg.QueryValueEx(key, "InstallDir")[0]
print(pro_path)
This prints:
C:\ArcGIS\Pro\
Here's a little esoterica about these flags used in line 5. These are integer flags, combined above with "|" which does a bitwise or operation. (Adding the integers would work just as well.) The idea of the integer flags is they allow the developers to cram multiple boolean flags in one integer value since the bit locations are set up to be different for each flag. This makes more sense when you look at the numbers in hex. Imagine a function that has many flags to control what it does. This technique allows you to cram as many as 32 values into a single 32-bit integer, simplifying your argument call dramatically.
I needed both of these flags to get my function to work: KEY_WOW_64KEY forces a 64-bit 'view' of the registry so my 32-bit app can read 64-bit keys, and KEY_READ makes sure I open the registry read-only (this avoid access errors).
>>> flags = [_winreg.KEY_READ, _winreg.KEY_WOW64_64KEY]
>>> flags.append(flags[0] | flags[1]) # bitwise OR
>>> flags
[131097, 256, 131353]
>>> ["0x{:08x}".format(f) for f in flags] # print in hex
['0x00020019', '0x00000100', '0x00020119']