Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

selecttlb.py 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. """Utilities for selecting and enumerating the Type Libraries installed on the system
  2. """
  3. import pythoncom
  4. import win32api
  5. import win32con
  6. class TypelibSpec:
  7. def __init__(self, clsid, lcid, major, minor, flags=0):
  8. self.clsid = str(clsid)
  9. self.lcid = int(lcid)
  10. # We avoid assuming 'major' or 'minor' are integers - when
  11. # read from the registry there is some confusion about if
  12. # they are base 10 or base 16 (they *should* be base 16, but
  13. # how they are written is beyond our control.)
  14. self.major = major
  15. self.minor = minor
  16. self.dll = None
  17. self.desc = None
  18. self.ver_desc = None
  19. self.flags = flags
  20. # For the SelectList
  21. def __getitem__(self, item):
  22. if item == 0:
  23. return self.ver_desc
  24. raise IndexError("Cant index me!")
  25. def __lt__(self, other): # rich-cmp/py3k-friendly version
  26. me = (
  27. (self.ver_desc or "").lower(),
  28. (self.desc or "").lower(),
  29. self.major,
  30. self.minor,
  31. )
  32. them = (
  33. (other.ver_desc or "").lower(),
  34. (other.desc or "").lower(),
  35. other.major,
  36. other.minor,
  37. )
  38. return me < them
  39. def __eq__(self, other): # rich-cmp/py3k-friendly version
  40. return (
  41. (self.ver_desc or "").lower() == (other.ver_desc or "").lower()
  42. and (self.desc or "").lower() == (other.desc or "").lower()
  43. and self.major == other.major
  44. and self.minor == other.minor
  45. )
  46. def Resolve(self):
  47. if self.dll is None:
  48. return 0
  49. tlb = pythoncom.LoadTypeLib(self.dll)
  50. self.FromTypelib(tlb, None)
  51. return 1
  52. def FromTypelib(self, typelib, dllName=None):
  53. la = typelib.GetLibAttr()
  54. self.clsid = str(la[0])
  55. self.lcid = la[1]
  56. self.major = la[3]
  57. self.minor = la[4]
  58. if dllName:
  59. self.dll = dllName
  60. def EnumKeys(root):
  61. index = 0
  62. ret = []
  63. while 1:
  64. try:
  65. item = win32api.RegEnumKey(root, index)
  66. except win32api.error:
  67. break
  68. try:
  69. # Note this doesn't handle REG_EXPAND_SZ, but the implementation
  70. # here doesn't need to - that is handled as the data is read.
  71. val = win32api.RegQueryValue(root, item)
  72. except win32api.error:
  73. val = "" # code using this assumes a string.
  74. ret.append((item, val))
  75. index = index + 1
  76. return ret
  77. FLAG_RESTRICTED = 1
  78. FLAG_CONTROL = 2
  79. FLAG_HIDDEN = 4
  80. def EnumTlbs(excludeFlags=0):
  81. """Return a list of TypelibSpec objects, one for each registered library."""
  82. key = win32api.RegOpenKey(win32con.HKEY_CLASSES_ROOT, "Typelib")
  83. iids = EnumKeys(key)
  84. results = []
  85. for iid, crap in iids:
  86. try:
  87. key2 = win32api.RegOpenKey(key, str(iid))
  88. except win32api.error:
  89. # A few good reasons for this, including "access denied".
  90. continue
  91. for version, tlbdesc in EnumKeys(key2):
  92. major_minor = version.split(".", 1)
  93. if len(major_minor) < 2:
  94. major_minor.append("0")
  95. # For some reason, this code used to assume the values were hex.
  96. # This seems to not be true - particularly for CDO 1.21
  97. # *sigh* - it appears there are no rules here at all, so when we need
  98. # to know the info, we must load the tlb by filename and request it.
  99. # The Resolve() method on the TypelibSpec does this.
  100. # For this reason, keep the version numbers as strings - that
  101. # way we can't be wrong! Let code that really needs an int to work
  102. # out what to do. FWIW, http://support.microsoft.com/kb/816970 is
  103. # pretty clear that they *should* be hex.
  104. major = major_minor[0]
  105. minor = major_minor[1]
  106. key3 = win32api.RegOpenKey(key2, str(version))
  107. try:
  108. # The "FLAGS" are at this point
  109. flags = int(win32api.RegQueryValue(key3, "FLAGS"))
  110. except (win32api.error, ValueError):
  111. flags = 0
  112. if flags & excludeFlags == 0:
  113. for lcid, crap in EnumKeys(key3):
  114. try:
  115. lcid = int(lcid)
  116. except ValueError: # not an LCID entry
  117. continue
  118. # Check for both "{lcid}\win32" and "{lcid}\win64" keys.
  119. try:
  120. key4 = win32api.RegOpenKey(key3, "%s\\win32" % (lcid,))
  121. except win32api.error:
  122. try:
  123. key4 = win32api.RegOpenKey(key3, "%s\\win64" % (lcid,))
  124. except win32api.error:
  125. continue
  126. try:
  127. dll, typ = win32api.RegQueryValueEx(key4, None)
  128. if typ == win32con.REG_EXPAND_SZ:
  129. dll = win32api.ExpandEnvironmentStrings(dll)
  130. except win32api.error:
  131. dll = None
  132. spec = TypelibSpec(iid, lcid, major, minor, flags)
  133. spec.dll = dll
  134. spec.desc = tlbdesc
  135. spec.ver_desc = tlbdesc + " (" + version + ")"
  136. results.append(spec)
  137. return results
  138. def FindTlbsWithDescription(desc):
  139. """Find all installed type libraries with the specified description"""
  140. ret = []
  141. items = EnumTlbs()
  142. for item in items:
  143. if item.desc == desc:
  144. ret.append(item)
  145. return ret
  146. def SelectTlb(title="Select Library", excludeFlags=0):
  147. """Display a list of all the type libraries, and select one. Returns None if cancelled"""
  148. import pywin.dialogs.list
  149. items = EnumTlbs(excludeFlags)
  150. # fixup versions - we assume hex (see __init__ above)
  151. for i in items:
  152. i.major = int(i.major, 16)
  153. i.minor = int(i.minor, 16)
  154. items.sort()
  155. rc = pywin.dialogs.list.SelectFromLists(title, items, ["Type Library"])
  156. if rc is None:
  157. return None
  158. return items[rc]
  159. # Test code.
  160. if __name__ == "__main__":
  161. print(SelectTlb().__dict__)