diff --git a/windows/check_gtk_install.py b/windows/check_gtk_install.py new file mode 100644 index 000000000..016afb767 --- /dev/null +++ b/windows/check_gtk_install.py @@ -0,0 +1,369 @@ +# +# Gramps - a GTK+ based genealogy program +# +# Copyright (C) 2010 Stephen George +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# $Id: $ +import sys +import os +import _winreg +from ctypes.util import find_library +import getopt +import string + +NOT_FOUND_STR ='Not Found' +#small selection of DLL's to test +testdlls = ['libgdk-win32-2.0-0.dll', 'libglib-2.0-0.dll', 'libgobject-2.0-0.dll', 'libcairo-2.dll', ] + +explain_exposed = ''' *********************************************************** + * It seems that other installations are exposing GTK DLL's + * to the operating system as they are in the environment + * path variable BEFORE the runtime directory. + * You should reorder the path variable to put your GTK + * runtime path before these other installations on the path''' + +explain_safe = ''' *************************************************************** + * While there are other installations of GTK DLL's on the path, + * it should be safe as they are on the path AFTER the runtime + * directory. ''' + +def RunExeCommand( app, args ): + cmd = app + ' ' + args + #print "Running: ", cmd + stdin, stdout, stderr = os.popen3( cmd ) + output = string.strip(stdout.read()) + #print output + err = stderr.read() + if err: + print err + return output + +def CheckGtkInReg(): + global gtkPathInRegistry, gtkVersionInRegistry, dllPathInRegistry, dllPathShort + print '\n==== Checking Registry for GTK =====' + try: + with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\GTK\\2.0') as key: + gtkVersionInRegistry = _winreg.QueryValueEx(key, 'Version')[0] + gtkPathInRegistry = _winreg.QueryValueEx(key, 'Path')[0] + dllPathInRegistry = _winreg.QueryValueEx(key, 'DllPath')[0] + print ' Version :', gtkVersionInRegistry + print ' Path :', gtkPathInRegistry + print ' DllPath :', dllPathInRegistry + + except WindowsError, e: + print '\n GTK registry key not found in registry' + print ''' ******************************************************************** + * This might not be an error, but means I don't know the directory to + * your preferred GTK installation. + * - try passing in your GTK installation path.\n''' + print '-' * 60 + print usage + sys.exit(0) + +def WorkOutShortDosPath(): + global dllPathShort + print '\n==== Use win32Api to query short path name for GTK =====' + try: + import win32api + dllPathShort = win32api.GetShortPathName(dllPathInRegistry) + print ' DllPath8.3:', dllPathShort + except ImportError: + print ' **Cant query short path name, Win32Api not installed' + print ' install from http://python.net/crew/mhammond/win32/' + print ' if you want this function to work' + +def FindLibsWithCtypes(): + # use ctypes to check where windows finds it's DLL's + print '\n==== Use ctypes to find dlls ====' + other_paths = [] + for dll in testdlls: + dllpathvalid = False + cpath = find_library(dll) + if cpath: + #print cpath + if cpath == os.path.join(dllPathInRegistry, dll) \ + or cpath == os.path.join(dllPathShort, dll): + dllpathvalid = True + + if not dllpathvalid: + pp = os.path.dirname(cpath) + if pp not in other_paths: + other_paths.append(pp) + else: + print " ERROR:... ctypes failed to find %s" % dll + if other_paths: + for pth in other_paths: + print " ERROR: ctypes loaded some gtk dll's from %s" % pth + else: + print " OK ... ctypes found dll's in %s" % os.path.dirname(cpath) + +def ScanDependencyFileForErrors(fname): + fin = open(fname, 'r') + lines = fin.readlines() + fin.close() + sysroot = os.environ["SystemRoot"] + capture = False + runtimedlls = {} + for line in lines: + if line.startswith(" Module"): # work out were paths end + pthend_idx = line.find("File Time Stamp") + acceptablePaths = [ dllPathShort.lower(), + dllPathInRegistry.lower(), + os.path.join(sysroot, 'system32').lower() + ] + if line.startswith('----- ------------'): + capture = True + if capture and line.startswith('['): + filename = line[5:pthend_idx].strip() + dirname = os.path.dirname(filename).strip() + parts = line[pthend_idx:].split() + OK = False + if dirname.startswith(os.path.join(sysroot, 'winsxs').lower()) \ + or dirname.startswith(os.path.join(sys.prefix, 'lib\site-packages\gtk-2.0').lower()): + OK = True + + for pth in acceptablePaths: + if dirname == pth.lower(): + OK = True + + if 'MSVCR90.DLL' in filename: + if parts[0] == 'Error': + runtimedlls[filename] = "Error dll not found" + else: + runtimedlls[filename] = parts[16] + + if OK == False: + if parts[0] == 'Error': + print " %s \tError dll not found" %( filename) + else: + print " ERROR: %s \tVersion %s" %( filename, parts[16]) + for rtdll in runtimedlls: + if runtimedlls[rtdll].startswith("Error"): + print '\n ERROR: MS runtime %s not found'%rtdll + else: + print '\n MS runtime Version %s loaded from' % runtimedlls[rtdll] + print " %s" %rtdll + print + +def CheckWithDependencyWalker(): + print '\n==== Checking with Dependency Walker ====' + print ' Please be patient takes some time' + exe = os.path.join(scriptpath, 'depends.exe') + fout = os.path.join(scriptpath, 'depres.txt') + f2check = [ + os.path.join(sys.prefix, 'Lib/site-packages/gtk-2.0/gtk/_gtk.pyd' ), + os.path.join(sys.prefix, 'Lib/site-packages/gtk-2.0/gobject/_gobject.pyd' ), + os.path.join(sys.prefix, 'Lib/site-packages/gtk-2.0/pangocairo.pyd' ), + ] + if os.path.isfile( exe ): + for ftest in f2check: + if os.path.isfile( ftest ): + #delete the output file before running command + try: + os.remove(fout) + except WindowsError, e: + pass + print ' Testing file %s' % ftest + out = RunExeCommand(exe, '/c /f1 /ot "%s" "%s"' % (fout, ftest) ) + if os.path.isfile(fout): + ScanDependencyFileForErrors(fout) + else: + print " ERROR: file %d does not exist", ftest + else: + print ' Cannot check with dependency walker, not installed in local directory' + print ' get dependency walker from http://www.dependencywalker.com/' + print ' and unzip into this directory for it to work.' + +def CheckPathForOtherGtkInstalls(): + print '\n====Checking environment path for other gtk installations====' + ePath = os.environ['path'] + dirs = ePath.split(';') + gtkpth_idx = 9999 + other_paths = [] + explain_level = 0 + for i, d in enumerate(dirs): + #print '==%s==' %d + if d == gtkPathInRegistry or d == dllPathInRegistry\ + or d == dllPathShort: + gtkpth_idx = i + continue + for fname in testdlls: + f = os.path.join(d, fname) + if os.path.isfile( f ): + #print ' Found Erronous gtk DLL %s' % f + if d not in other_paths: + other_paths.append(d) + if i < gtkpth_idx: # path appears BEFORE runtime path + print ' ERROR: %s should not appear before runtime path' % d + explain_level = 2 + else: + print ' FOUND: %s, Probably OK as appears AFTER runtime path' % d + if explain_level <= 1: + explain_level = 1 + if gtkpth_idx == 9999: + print '\n ERROR: Runtime directory not on enviroment path' + print " ** Runtime needs to be on path to load DLL's from\n" + if explain_level == 2: + print explain_exposed + elif explain_level == 1: + print explain_safe + if len(other_paths) == 0: + print ' No other gtk installatons found\n' + +# ==== report what python thinks it's using ===== +MIN_PYTHON_VER = (2,5,1) +UNTESTED_PYTHON_VER = (3,0,0) + +MIN_GTK_VER = (2,10,11) +UNTESTED_GTK_VER = (2,16,7) + +MIN_PYGTK_VER = (2,10,6) +UNTESTED_PYGTK_VER = (2,12,2) + +MIN_GOBJECT_VER = (2,12,3) +UNTESTED_GOBJECT_VER = (2,14,3) + +MIN_CAIRO_VER = (1,2,6) +UNTESTED_CAIRO_VER = (1,4,13) + +def PrintFailedImport(appl, minVersion, result): + print appl, + print 'version %d.%d.%d or above.....\t' % minVersion , + print result + +def PrintVersionResult(appl, minVersion, actualVersion, untestedVersion): + print appl, + print 'version %d.%d.%d or above.....\t' % minVersion , + print 'found %d.%d.%d' % actualVersion , + if minVersion <= actualVersion < untestedVersion: + print '...OK' + elif actualVersion >= untestedVersion: + print '...UNTESTED VERSION' + else: + print '...FAILED' + +def Import_pyGtkIntoPython(): + print '\n==== Test import into python ====' + #py_str = 'found %d.%d.%d' % sys.version_info[:3] + PrintVersionResult(' Python ', MIN_PYTHON_VER, sys.version_info[:3], UNTESTED_PYTHON_VER) + + # Test the GTK version + try: + import gtk + + PrintVersionResult(' GTK+ ', MIN_GTK_VER, gtk.gtk_version, UNTESTED_GTK_VER ) + + #test the pyGTK version (which is in the gtk namespace) + PrintVersionResult(' pyGTK ', MIN_PYGTK_VER, gtk.pygtk_version, UNTESTED_PYGTK_VER ) + + except ImportError: + PrintFailedImport(' GTK+ ', MIN_GTK_VER, NOT_FOUND_STR) + PrintFailedImport(' pyGTK ', MIN_PYGTK_VER, 'Cannot test, ...GTK+ missing') + + + #test the gobject version + try: + import gobject + PrintVersionResult(' gobject', MIN_GOBJECT_VER, gobject.pygobject_version, UNTESTED_GOBJECT_VER) + + except ImportError: + PrintFailedImport(' gobject', MIN_GOBJECT_VER, NOT_FOUND_STR) + + + #test the cairo version + try: + import cairo + PrintVersionResult(' cairo ', MIN_CAIRO_VER, cairo.version_info, UNTESTED_CAIRO_VER ) + + except ImportError: + PrintFailedImport(' cairo ', MIN_CAIRO_VER, NOT_FOUND_STR) + + #test for glade + print '\n==== See if libglade installed ====' + + try: + import gtk.glade + print ' Glade tesing import of libglade .......\tOK\n' + except ImportError, e: + print ' Glade importError: %s\n' % e + +if __name__ == '__main__': + usage = '''Check for common problems in GTK/pyGTK installation. +Usage: + python %s [options] [gtkPath] + +Arguments: + gtkPath Path to your GTK installation directory (not the bin dir) + +Options: + None + ''' %(os.path.basename(__file__) ) + + gtkPath = None + gtkPathInRegistry = NOT_FOUND_STR + gtkVersionInRegistry = NOT_FOUND_STR + dllPathInRegistry = NOT_FOUND_STR + dllPathShort = 'NoShortPath' + scriptpath = os.path.dirname(sys.argv[0]) + try: + opts, args = getopt.getopt(sys.argv[1:], "", + []) + + for o, a in opts: + if o in ("-h", "--help"): + print usage + sys.exit(0) + + if len(args) > 1: + raise getopt.GetoptError, '\nERROR: Too many arguments' + for arg in args: + if os.path.isdir(arg): + gtkPath = arg + else: + raise getopt.GetoptError, '\nERROR: Not a valid GTK path %s' % arg + + except getopt.GetoptError, msg: + print msg + print '\n %s' % usage + sys.exit(2) + + import platform + winver = platform.win32_ver() + if len(winver) == 4: + print '''\n==== platform.win32_ver() reports ==== + Operating System: %s + Version : %s + Service Pack : %s + OS type : %s''' % winver + else: + print winver + + if gtkPath: + gtkPathInRegistry = gtkPath + dllPathInRegistry = os.path.join(gtkPath, 'bin') + print ' Using %s as GTK install path' % gtkPathInRegistry + print ' Using %s as GTK dll path' % dllPathInRegistry + else: + CheckGtkInReg() + + WorkOutShortDosPath() + FindLibsWithCtypes() + CheckPathForOtherGtkInstalls() + Import_pyGtkIntoPython() + + CheckWithDependencyWalker() +