285 lines
11 KiB
Python
285 lines
11 KiB
Python
|
# Some registry helpers.
|
||
|
import win32api
|
||
|
import win32con
|
||
|
import sys
|
||
|
import os
|
||
|
|
||
|
error = "Registry utility error"
|
||
|
|
||
|
# A .py file has a CLSID associated with it (why? - dunno!)
|
||
|
CLSIDPyFile = "{b51df050-06ae-11cf-ad3b-524153480001}"
|
||
|
|
||
|
RegistryIDPyFile = "Python.File" # The registry "file type" of a .py file
|
||
|
RegistryIDPycFile = "Python.CompiledFile" # The registry "file type" of a .pyc file
|
||
|
|
||
|
def BuildDefaultPythonKey():
|
||
|
"""Builds a string containing the path to the current registry key.
|
||
|
|
||
|
The Python registry key contains the Python version. This function
|
||
|
uses the version of the DLL used by the current process to get the
|
||
|
registry key currently in use.
|
||
|
"""
|
||
|
return "Software\\Python\\PythonCore\\" + sys.winver
|
||
|
|
||
|
def GetRootKey():
|
||
|
"""Retrieves the Registry root in use by Python.
|
||
|
"""
|
||
|
keyname = BuildDefaultPythonKey()
|
||
|
try:
|
||
|
k = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, keyname)
|
||
|
k.close()
|
||
|
return win32con.HKEY_CURRENT_USER
|
||
|
except win32api.error:
|
||
|
return win32con.HKEY_LOCAL_MACHINE
|
||
|
|
||
|
def GetRegistryDefaultValue(subkey, rootkey = None):
|
||
|
"""A helper to return the default value for a key in the registry.
|
||
|
"""
|
||
|
if rootkey is None: rootkey = GetRootKey()
|
||
|
return win32api.RegQueryValue(rootkey, subkey)
|
||
|
|
||
|
def SetRegistryDefaultValue(subKey, value, rootkey = None):
|
||
|
"""A helper to set the default value for a key in the registry
|
||
|
"""
|
||
|
if rootkey is None: rootkey = GetRootKey()
|
||
|
if type(value)==str:
|
||
|
typeId = win32con.REG_SZ
|
||
|
elif type(value)==int:
|
||
|
typeId = win32con.REG_DWORD
|
||
|
else:
|
||
|
raise TypeError("Value must be string or integer - was passed " + repr(value))
|
||
|
|
||
|
win32api.RegSetValue(rootkey, subKey, typeId ,value)
|
||
|
|
||
|
def GetAppPathsKey():
|
||
|
return "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths"
|
||
|
|
||
|
def RegisterPythonExe(exeFullPath, exeAlias = None, exeAppPath = None):
|
||
|
"""Register a .exe file that uses Python.
|
||
|
|
||
|
Registers the .exe with the OS. This allows the specified .exe to
|
||
|
be run from the command-line or start button without using the full path,
|
||
|
and also to setup application specific path (ie, os.environ['PATH']).
|
||
|
|
||
|
Currently the exeAppPath is not supported, so this function is general
|
||
|
purpose, and not specific to Python at all. Later, exeAppPath may provide
|
||
|
a reasonable default that is used.
|
||
|
|
||
|
exeFullPath -- The full path to the .exe
|
||
|
exeAlias = None -- An alias for the exe - if none, the base portion
|
||
|
of the filename is used.
|
||
|
exeAppPath -- Not supported.
|
||
|
"""
|
||
|
# Note - Dont work on win32s (but we dont care anymore!)
|
||
|
if exeAppPath:
|
||
|
raise error("Do not support exeAppPath argument currently")
|
||
|
if exeAlias is None:
|
||
|
exeAlias = os.path.basename(exeFullPath)
|
||
|
win32api.RegSetValue(GetRootKey(), GetAppPathsKey() + "\\" + exeAlias, win32con.REG_SZ, exeFullPath)
|
||
|
|
||
|
def GetRegisteredExe(exeAlias):
|
||
|
"""Get a registered .exe
|
||
|
"""
|
||
|
return win32api.RegQueryValue(GetRootKey(), GetAppPathsKey() + "\\" + exeAlias)
|
||
|
|
||
|
def UnregisterPythonExe(exeAlias):
|
||
|
"""Unregister a .exe file that uses Python.
|
||
|
"""
|
||
|
try:
|
||
|
win32api.RegDeleteKey(GetRootKey(), GetAppPathsKey() + "\\" + exeAlias)
|
||
|
except win32api.error as exc:
|
||
|
import winerror
|
||
|
if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND:
|
||
|
raise
|
||
|
return
|
||
|
|
||
|
def RegisterNamedPath(name, path):
|
||
|
"""Register a named path - ie, a named PythonPath entry.
|
||
|
"""
|
||
|
keyStr = BuildDefaultPythonKey() + "\\PythonPath"
|
||
|
if name: keyStr = keyStr + "\\" + name
|
||
|
win32api.RegSetValue(GetRootKey(), keyStr, win32con.REG_SZ, path)
|
||
|
|
||
|
def UnregisterNamedPath(name):
|
||
|
"""Unregister a named path - ie, a named PythonPath entry.
|
||
|
"""
|
||
|
keyStr = BuildDefaultPythonKey() + "\\PythonPath\\" + name
|
||
|
try:
|
||
|
win32api.RegDeleteKey(GetRootKey(), keyStr)
|
||
|
except win32api.error as exc:
|
||
|
import winerror
|
||
|
if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND:
|
||
|
raise
|
||
|
return
|
||
|
|
||
|
def GetRegisteredNamedPath(name):
|
||
|
"""Get a registered named path, or None if it doesnt exist.
|
||
|
"""
|
||
|
keyStr = BuildDefaultPythonKey() + "\\PythonPath"
|
||
|
if name: keyStr = keyStr + "\\" + name
|
||
|
try:
|
||
|
return win32api.RegQueryValue(GetRootKey(), keyStr)
|
||
|
except win32api.error as exc:
|
||
|
import winerror
|
||
|
if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND:
|
||
|
raise
|
||
|
return None
|
||
|
|
||
|
|
||
|
def RegisterModule(modName, modPath):
|
||
|
"""Register an explicit module in the registry. This forces the Python import
|
||
|
mechanism to locate this module directly, without a sys.path search. Thus
|
||
|
a registered module need not appear in sys.path at all.
|
||
|
|
||
|
modName -- The name of the module, as used by import.
|
||
|
modPath -- The full path and file name of the module.
|
||
|
"""
|
||
|
try:
|
||
|
import os
|
||
|
os.stat(modPath)
|
||
|
except os.error:
|
||
|
print("Warning: Registering non-existant module %s" % modPath)
|
||
|
win32api.RegSetValue(GetRootKey(),
|
||
|
BuildDefaultPythonKey() + "\\Modules\\%s" % modName,
|
||
|
win32con.REG_SZ, modPath)
|
||
|
|
||
|
def UnregisterModule(modName):
|
||
|
"""Unregister an explicit module in the registry.
|
||
|
|
||
|
modName -- The name of the module, as used by import.
|
||
|
"""
|
||
|
try:
|
||
|
win32api.RegDeleteKey(GetRootKey(),
|
||
|
BuildDefaultPythonKey() + "\\Modules\\%s" % modName)
|
||
|
except win32api.error as exc:
|
||
|
import winerror
|
||
|
if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND:
|
||
|
raise
|
||
|
|
||
|
def GetRegisteredHelpFile(helpDesc):
|
||
|
"""Given a description, return the registered entry.
|
||
|
"""
|
||
|
try:
|
||
|
return GetRegistryDefaultValue(BuildDefaultPythonKey() + "\\Help\\" + helpDesc)
|
||
|
except win32api.error:
|
||
|
try:
|
||
|
return GetRegistryDefaultValue(BuildDefaultPythonKey() + "\\Help\\" + helpDesc, win32con.HKEY_CURRENT_USER)
|
||
|
except win32api.error:
|
||
|
pass
|
||
|
return None
|
||
|
|
||
|
def RegisterHelpFile(helpFile, helpPath, helpDesc = None, bCheckFile = 1):
|
||
|
"""Register a help file in the registry.
|
||
|
|
||
|
Note that this used to support writing to the Windows Help
|
||
|
key, however this is no longer done, as it seems to be incompatible.
|
||
|
|
||
|
helpFile -- the base name of the help file.
|
||
|
helpPath -- the path to the help file
|
||
|
helpDesc -- A description for the help file. If None, the helpFile param is used.
|
||
|
bCheckFile -- A flag indicating if the file existence should be checked.
|
||
|
"""
|
||
|
if helpDesc is None: helpDesc = helpFile
|
||
|
fullHelpFile = os.path.join(helpPath, helpFile)
|
||
|
try:
|
||
|
if bCheckFile: os.stat(fullHelpFile)
|
||
|
except os.error:
|
||
|
raise ValueError("Help file does not exist")
|
||
|
# Now register with Python itself.
|
||
|
win32api.RegSetValue(GetRootKey(),
|
||
|
BuildDefaultPythonKey() + "\\Help\\%s" % helpDesc, win32con.REG_SZ, fullHelpFile)
|
||
|
|
||
|
def UnregisterHelpFile(helpFile, helpDesc = None):
|
||
|
"""Unregister a help file in the registry.
|
||
|
|
||
|
helpFile -- the base name of the help file.
|
||
|
helpDesc -- A description for the help file. If None, the helpFile param is used.
|
||
|
"""
|
||
|
key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Help", 0, win32con.KEY_ALL_ACCESS)
|
||
|
try:
|
||
|
try:
|
||
|
win32api.RegDeleteValue(key, helpFile)
|
||
|
except win32api.error as exc:
|
||
|
import winerror
|
||
|
if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND:
|
||
|
raise
|
||
|
finally:
|
||
|
win32api.RegCloseKey(key)
|
||
|
|
||
|
# Now de-register with Python itself.
|
||
|
if helpDesc is None: helpDesc = helpFile
|
||
|
try:
|
||
|
win32api.RegDeleteKey(GetRootKey(),
|
||
|
BuildDefaultPythonKey() + "\\Help\\%s" % helpDesc)
|
||
|
except win32api.error as exc:
|
||
|
import winerror
|
||
|
if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND:
|
||
|
raise
|
||
|
|
||
|
def RegisterCoreDLL(coredllName = None):
|
||
|
"""Registers the core DLL in the registry.
|
||
|
|
||
|
If no params are passed, the name of the Python DLL used in
|
||
|
the current process is used and registered.
|
||
|
"""
|
||
|
if coredllName is None:
|
||
|
coredllName = win32api.GetModuleFileName(sys.dllhandle)
|
||
|
# must exist!
|
||
|
else:
|
||
|
try:
|
||
|
os.stat(coredllName)
|
||
|
except os.error:
|
||
|
print("Warning: Registering non-existant core DLL %s" % coredllName)
|
||
|
|
||
|
hKey = win32api.RegCreateKey(GetRootKey() , BuildDefaultPythonKey())
|
||
|
try:
|
||
|
win32api.RegSetValue(hKey, "Dll", win32con.REG_SZ, coredllName)
|
||
|
finally:
|
||
|
win32api.RegCloseKey(hKey)
|
||
|
# Lastly, setup the current version to point to me.
|
||
|
win32api.RegSetValue(GetRootKey(), "Software\\Python\\PythonCore\\CurrentVersion", win32con.REG_SZ, sys.winver)
|
||
|
|
||
|
def RegisterFileExtensions(defPyIcon, defPycIcon, runCommand):
|
||
|
"""Register the core Python file extensions.
|
||
|
|
||
|
defPyIcon -- The default icon to use for .py files, in 'fname,offset' format.
|
||
|
defPycIcon -- The default icon to use for .pyc files, in 'fname,offset' format.
|
||
|
runCommand -- The command line to use for running .py files
|
||
|
"""
|
||
|
# Register the file extensions.
|
||
|
pythonFileId = RegistryIDPyFile
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , ".py", win32con.REG_SZ, pythonFileId)
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , pythonFileId , win32con.REG_SZ, "Python File")
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , "%s\\CLSID" % pythonFileId , win32con.REG_SZ, CLSIDPyFile)
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , "%s\\DefaultIcon" % pythonFileId, win32con.REG_SZ, defPyIcon)
|
||
|
base = "%s\\Shell" % RegistryIDPyFile
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\Open", win32con.REG_SZ, "Run")
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\Open\\Command", win32con.REG_SZ, runCommand)
|
||
|
|
||
|
# Register the .PYC.
|
||
|
pythonFileId = RegistryIDPycFile
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , ".pyc", win32con.REG_SZ, pythonFileId)
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , pythonFileId , win32con.REG_SZ, "Compiled Python File")
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , "%s\\DefaultIcon" % pythonFileId, win32con.REG_SZ, defPycIcon)
|
||
|
base = "%s\\Shell" % pythonFileId
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\Open", win32con.REG_SZ, "Run")
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\Open\\Command", win32con.REG_SZ, runCommand)
|
||
|
|
||
|
def RegisterShellCommand(shellCommand, exeCommand, shellUserCommand = None):
|
||
|
# Last param for "Open" - for a .py file to be executed by the command line
|
||
|
# or shell execute (eg, just entering "foo.py"), the Command must be "Open",
|
||
|
# but you may associate a different name for the right-click menu.
|
||
|
# In our case, normally we have "Open=Run"
|
||
|
base = "%s\\Shell" % RegistryIDPyFile
|
||
|
if shellUserCommand:
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\%s" % (shellCommand), win32con.REG_SZ, shellUserCommand)
|
||
|
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\%s\\Command" % (shellCommand), win32con.REG_SZ, exeCommand)
|
||
|
|
||
|
def RegisterDDECommand(shellCommand, ddeApp, ddeTopic, ddeCommand):
|
||
|
base = "%s\\Shell" % RegistryIDPyFile
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\%s\\ddeexec" % (shellCommand), win32con.REG_SZ, ddeCommand)
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\%s\\ddeexec\\Application" % (shellCommand), win32con.REG_SZ, ddeApp)
|
||
|
win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\%s\\ddeexec\\Topic" % (shellCommand), win32con.REG_SZ, ddeTopic)
|
||
|
|