codekingpro/portable-devtools
114k
1"""A utility for browsing COM objects.2 3 Usage:4 5 Command Prompt6 7 Use the command *"python.exe combrowse.py"*. This will display8 display a fairly small, modal dialog.9 10 Pythonwin11 12 Use the "Run Script" menu item, and this will create the browser in an13 MDI window. This window can be fully resized.14 15 Details16 17 This module allows browsing of registered Type Libraries, COM categories,18 and running COM objects. The display is similar to the Pythonwin object19 browser, and displays the objects in a hierarchical window.20 21 Note that this module requires the win32ui (ie, Pythonwin) distribution to22 work.23 24"""25import sys26 27import pythoncom28import win32api29import win32con30import win32ui31from pywin.tools import browser32from win32com.client import util33 34 35class HLIRoot(browser.HLIPythonObject):36 def __init__(self, title):37 super().__init__(name=title)38 39 def GetSubList(self):40 return [41 HLIHeadingCategory(),42 HLI_IEnumMoniker(43 pythoncom.GetRunningObjectTable().EnumRunning(), "Running Objects"44 ),45 HLIHeadingRegisterdTypeLibs(),46 ]47 48 def __cmp__(self, other):49 return cmp(self.name, other.name)50 51 52class HLICOM(browser.HLIPythonObject):53 def GetText(self):54 return self.name55 56 def CalculateIsExpandable(self):57 return 158 59 60class HLICLSID(HLICOM):61 def __init__(self, myobject, name=None):62 if type(myobject) == type(""):63 myobject = pythoncom.MakeIID(myobject)64 if name is None:65 try:66 name = pythoncom.ProgIDFromCLSID(myobject)67 except pythoncom.com_error:68 name = str(myobject)69 name = "IID: " + name70 HLICOM.__init__(self, myobject, name)71 72 def CalculateIsExpandable(self):73 return 074 75 def GetSubList(self):76 return []77 78 79class HLI_Interface(HLICOM):80 pass81 82 83class HLI_Enum(HLI_Interface):84 def GetBitmapColumn(self):85 return 0 # Always a folder.86 87 def CalculateIsExpandable(self):88 if self.myobject is not None:89 rc = len(self.myobject.Next(1)) > 090 self.myobject.Reset()91 else:92 rc = 093 return rc94 95 pass96 97 98class HLI_IEnumMoniker(HLI_Enum):99 def GetSubList(self):100 ctx = pythoncom.CreateBindCtx()101 ret = []102 for mon in util.Enumerator(self.myobject):103 ret.append(HLI_IMoniker(mon, mon.GetDisplayName(ctx, None)))104 return ret105 106 107class HLI_IMoniker(HLI_Interface):108 def GetSubList(self):109 ret = []110 ret.append(browser.MakeHLI(self.myobject.Hash(), "Hash Value"))111 subenum = self.myobject.Enum(1)112 ret.append(HLI_IEnumMoniker(subenum, "Sub Monikers"))113 return ret114 115 116class HLIHeadingCategory(HLICOM):117 "A tree heading for registered categories"118 119 def GetText(self):120 return "Registered Categories"121 122 def GetSubList(self):123 catinf = pythoncom.CoCreateInstance(124 pythoncom.CLSID_StdComponentCategoriesMgr,125 None,126 pythoncom.CLSCTX_INPROC,127 pythoncom.IID_ICatInformation,128 )129 enum = util.Enumerator(catinf.EnumCategories())130 ret = []131 try:132 for catid, lcid, desc in enum:133 ret.append(HLICategory((catid, lcid, desc)))134 except pythoncom.com_error:135 # Registered categories occasionally seem to give spurious errors.136 pass # Use what we already have.137 return ret138 139 140class HLICategory(HLICOM):141 "An actual Registered Category"142 143 def GetText(self):144 desc = self.myobject[2]145 if not desc:146 desc = "(unnamed category)"147 return desc148 149 def GetSubList(self):150 win32ui.DoWaitCursor(1)151 catid, lcid, desc = self.myobject152 catinf = pythoncom.CoCreateInstance(153 pythoncom.CLSID_StdComponentCategoriesMgr,154 None,155 pythoncom.CLSCTX_INPROC,156 pythoncom.IID_ICatInformation,157 )158 ret = []159 for clsid in util.Enumerator(catinf.EnumClassesOfCategories((catid,), ())):160 ret.append(HLICLSID(clsid))161 win32ui.DoWaitCursor(0)162 163 return ret164 165 166class HLIHelpFile(HLICOM):167 def CalculateIsExpandable(self):168 return 0169 170 def GetText(self):171 import os172 173 fname, ctx = self.myobject174 base = os.path.split(fname)[1]175 return "Help reference in %s" % (base)176 177 def TakeDefaultAction(self):178 fname, ctx = self.myobject179 if ctx:180 cmd = win32con.HELP_CONTEXT181 else:182 cmd = win32con.HELP_FINDER183 win32api.WinHelp(win32ui.GetMainFrame().GetSafeHwnd(), fname, cmd, ctx)184 185 def GetBitmapColumn(self):186 return 6187 188 189class HLIRegisteredTypeLibrary(HLICOM):190 def GetSubList(self):191 import os192 193 clsidstr, versionStr = self.myobject194 collected = []195 helpPath = ""196 key = win32api.RegOpenKey(197 win32con.HKEY_CLASSES_ROOT, "TypeLib\\%s\\%s" % (clsidstr, versionStr)198 )199 win32ui.DoWaitCursor(1)200 try:201 num = 0202 while 1:203 try:204 subKey = win32api.RegEnumKey(key, num)205 except win32api.error:206 break207 hSubKey = win32api.RegOpenKey(key, subKey)208 try:209 value, typ = win32api.RegQueryValueEx(hSubKey, None)210 if typ == win32con.REG_EXPAND_SZ:211 value = win32api.ExpandEnvironmentStrings(value)212 except win32api.error:213 value = ""214 if subKey == "HELPDIR":215 helpPath = value216 elif subKey == "Flags":217 flags = value218 else:219 try:220 lcid = int(subKey)221 lcidkey = win32api.RegOpenKey(key, subKey)222 # Enumerate the platforms223 lcidnum = 0224 while 1:225 try:226 platform = win32api.RegEnumKey(lcidkey, lcidnum)227 except win32api.error:228 break229 try:230 hplatform = win32api.RegOpenKey(lcidkey, platform)231 fname, typ = win32api.RegQueryValueEx(hplatform, None)232 if typ == win32con.REG_EXPAND_SZ:233 fname = win32api.ExpandEnvironmentStrings(fname)234 except win32api.error:235 fname = ""236 collected.append((lcid, platform, fname))237 lcidnum = lcidnum + 1238 win32api.RegCloseKey(lcidkey)239 except ValueError:240 pass241 num = num + 1242 finally:243 win32ui.DoWaitCursor(0)244 win32api.RegCloseKey(key)245 # Now, loop over my collected objects, adding a TypeLib and a HelpFile246 ret = []247 # if helpPath: ret.append(browser.MakeHLI(helpPath, "Help Path"))248 ret.append(HLICLSID(clsidstr))249 for lcid, platform, fname in collected:250 extraDescs = []251 if platform != "win32":252 extraDescs.append(platform)253 if lcid:254 extraDescs.append("locale=%s" % lcid)255 extraDesc = ""256 if extraDescs:257 extraDesc = " (%s)" % ", ".join(extraDescs)258 ret.append(HLITypeLib(fname, "Type Library" + extraDesc))259 ret.sort()260 return ret261 262 263class HLITypeLibEntry(HLICOM):264 def GetText(self):265 tlb, index = self.myobject266 name, doc, ctx, helpFile = tlb.GetDocumentation(index)267 try:268 typedesc = HLITypeKinds[tlb.GetTypeInfoType(index)][1]269 except KeyError:270 typedesc = "Unknown!"271 return name + " - " + typedesc272 273 def GetSubList(self):274 tlb, index = self.myobject275 name, doc, ctx, helpFile = tlb.GetDocumentation(index)276 ret = []277 if doc:278 ret.append(browser.HLIDocString(doc, "Doc"))279 if helpFile:280 ret.append(HLIHelpFile((helpFile, ctx)))281 return ret282 283 284class HLICoClass(HLITypeLibEntry):285 def GetSubList(self):286 ret = HLITypeLibEntry.GetSubList(self)287 tlb, index = self.myobject288 typeinfo = tlb.GetTypeInfo(index)289 attr = typeinfo.GetTypeAttr()290 for j in range(attr[8]):291 flags = typeinfo.GetImplTypeFlags(j)292 refType = typeinfo.GetRefTypeInfo(typeinfo.GetRefTypeOfImplType(j))293 refAttr = refType.GetTypeAttr()294 ret.append(295 browser.MakeHLI(refAttr[0], "Name=%s, Flags = %d" % (refAttr[0], flags))296 )297 return ret298 299 300class HLITypeLibMethod(HLITypeLibEntry):301 def __init__(self, ob, name=None):302 self.entry_type = "Method"303 HLITypeLibEntry.__init__(self, ob, name)304 305 def GetSubList(self):306 ret = HLITypeLibEntry.GetSubList(self)307 tlb, index = self.myobject308 typeinfo = tlb.GetTypeInfo(index)309 attr = typeinfo.GetTypeAttr()310 for i in range(attr[7]):311 ret.append(HLITypeLibProperty((typeinfo, i)))312 for i in range(attr[6]):313 ret.append(HLITypeLibFunction((typeinfo, i)))314 return ret315 316 317class HLITypeLibEnum(HLITypeLibEntry):318 def __init__(self, myitem):319 typelib, index = myitem320 typeinfo = typelib.GetTypeInfo(index)321 self.id = typeinfo.GetVarDesc(index)[0]322 name = typeinfo.GetNames(self.id)[0]323 HLITypeLibEntry.__init__(self, myitem, name)324 325 def GetText(self):326 return self.name + " - Enum/Module"327 328 def GetSubList(self):329 ret = []330 typelib, index = self.myobject331 typeinfo = typelib.GetTypeInfo(index)332 attr = typeinfo.GetTypeAttr()333 for j in range(attr[7]):334 vdesc = typeinfo.GetVarDesc(j)335 name = typeinfo.GetNames(vdesc[0])[0]336 ret.append(browser.MakeHLI(vdesc[1], name))337 return ret338 339 340class HLITypeLibProperty(HLICOM):341 def __init__(self, myitem):342 typeinfo, index = myitem343 self.id = typeinfo.GetVarDesc(index)[0]344 name = typeinfo.GetNames(self.id)[0]345 HLICOM.__init__(self, myitem, name)346 347 def GetText(self):348 return self.name + " - Property"349 350 def GetSubList(self):351 ret = []352 typeinfo, index = self.myobject353 names = typeinfo.GetNames(self.id)354 if len(names) > 1:355 ret.append(browser.MakeHLI(names[1:], "Named Params"))356 vd = typeinfo.GetVarDesc(index)357 ret.append(browser.MakeHLI(self.id, "Dispatch ID"))358 ret.append(browser.MakeHLI(vd[1], "Value"))359 ret.append(browser.MakeHLI(vd[2], "Elem Desc"))360 ret.append(browser.MakeHLI(vd[3], "Var Flags"))361 ret.append(browser.MakeHLI(vd[4], "Var Kind"))362 return ret363 364 365class HLITypeLibFunction(HLICOM):366 funckinds = {367 pythoncom.FUNC_VIRTUAL: "Virtual",368 pythoncom.FUNC_PUREVIRTUAL: "Pure Virtual",369 pythoncom.FUNC_STATIC: "Static",370 pythoncom.FUNC_DISPATCH: "Dispatch",371 }372 invokekinds = {373 pythoncom.INVOKE_FUNC: "Function",374 pythoncom.INVOKE_PROPERTYGET: "Property Get",375 pythoncom.INVOKE_PROPERTYPUT: "Property Put",376 pythoncom.INVOKE_PROPERTYPUTREF: "Property Put by reference",377 }378 funcflags = [379 (pythoncom.FUNCFLAG_FRESTRICTED, "Restricted"),380 (pythoncom.FUNCFLAG_FSOURCE, "Source"),381 (pythoncom.FUNCFLAG_FBINDABLE, "Bindable"),382 (pythoncom.FUNCFLAG_FREQUESTEDIT, "Request Edit"),383 (pythoncom.FUNCFLAG_FDISPLAYBIND, "Display Bind"),384 (pythoncom.FUNCFLAG_FDEFAULTBIND, "Default Bind"),385 (pythoncom.FUNCFLAG_FHIDDEN, "Hidden"),386 (pythoncom.FUNCFLAG_FUSESGETLASTERROR, "Uses GetLastError"),387 ]388 389 vartypes = {390 pythoncom.VT_EMPTY: "Empty",391 pythoncom.VT_NULL: "NULL",392 pythoncom.VT_I2: "Integer 2",393 pythoncom.VT_I4: "Integer 4",394 pythoncom.VT_R4: "Real 4",395 pythoncom.VT_R8: "Real 8",396 pythoncom.VT_CY: "CY",397 pythoncom.VT_DATE: "Date",398 pythoncom.VT_BSTR: "String",399 pythoncom.VT_DISPATCH: "IDispatch",400 pythoncom.VT_ERROR: "Error",401 pythoncom.VT_BOOL: "BOOL",402 pythoncom.VT_VARIANT: "Variant",403 pythoncom.VT_UNKNOWN: "IUnknown",404 pythoncom.VT_DECIMAL: "Decimal",405 pythoncom.VT_I1: "Integer 1",406 pythoncom.VT_UI1: "Unsigned integer 1",407 pythoncom.VT_UI2: "Unsigned integer 2",408 pythoncom.VT_UI4: "Unsigned integer 4",409 pythoncom.VT_I8: "Integer 8",410 pythoncom.VT_UI8: "Unsigned integer 8",411 pythoncom.VT_INT: "Integer",412 pythoncom.VT_UINT: "Unsigned integer",413 pythoncom.VT_VOID: "Void",414 pythoncom.VT_HRESULT: "HRESULT",415 pythoncom.VT_PTR: "Pointer",416 pythoncom.VT_SAFEARRAY: "SafeArray",417 pythoncom.VT_CARRAY: "C Array",418 pythoncom.VT_USERDEFINED: "User Defined",419 pythoncom.VT_LPSTR: "Pointer to string",420 pythoncom.VT_LPWSTR: "Pointer to Wide String",421 pythoncom.VT_FILETIME: "File time",422 pythoncom.VT_BLOB: "Blob",423 pythoncom.VT_STREAM: "IStream",424 pythoncom.VT_STORAGE: "IStorage",425 pythoncom.VT_STORED_OBJECT: "Stored object",426 pythoncom.VT_STREAMED_OBJECT: "Streamed object",427 pythoncom.VT_BLOB_OBJECT: "Blob object",428 pythoncom.VT_CF: "CF",429 pythoncom.VT_CLSID: "CLSID",430 }431 432 type_flags = [433 (pythoncom.VT_VECTOR, "Vector"),434 (pythoncom.VT_ARRAY, "Array"),435 (pythoncom.VT_BYREF, "ByRef"),436 (pythoncom.VT_RESERVED, "Reserved"),437 ]438 439 def __init__(self, myitem):440 typeinfo, index = myitem441 self.id = typeinfo.GetFuncDesc(index)[0]442 name = typeinfo.GetNames(self.id)[0]443 HLICOM.__init__(self, myitem, name)444 445 def GetText(self):446 return self.name + " - Function"447 448 def MakeReturnTypeName(self, typ):449 justtyp = typ & pythoncom.VT_TYPEMASK450 try:451 typname = self.vartypes[justtyp]452 except KeyError:453 typname = "?Bad type?"454 for flag, desc in self.type_flags:455 if flag & typ:456 typname = "%s(%s)" % (desc, typname)457 return typname458 459 def MakeReturnType(self, returnTypeDesc):460 if type(returnTypeDesc) == type(()):461 first = returnTypeDesc[0]462 result = self.MakeReturnType(first)463 if first != pythoncom.VT_USERDEFINED:464 result = result + " " + self.MakeReturnType(returnTypeDesc[1])465 return result466 else:467 return self.MakeReturnTypeName(returnTypeDesc)468 469 def GetSubList(self):470 ret = []471 typeinfo, index = self.myobject472 names = typeinfo.GetNames(self.id)473 ret.append(browser.MakeHLI(self.id, "Dispatch ID"))474 if len(names) > 1:475 ret.append(browser.MakeHLI(", ".join(names[1:]), "Named Params"))476 fd = typeinfo.GetFuncDesc(index)477 if fd[1]:478 ret.append(browser.MakeHLI(fd[1], "Possible result values"))479 if fd[8]:480 typ, flags, default = fd[8]481 val = self.MakeReturnType(typ)482 if flags:483 val = "%s (Flags=%d, default=%s)" % (val, flags, default)484 ret.append(browser.MakeHLI(val, "Return Type"))485 486 for argDesc in fd[2]:487 typ, flags, default = argDesc488 val = self.MakeReturnType(typ)489 if flags:490 val = "%s (Flags=%d)" % (val, flags)491 if default is not None:492 val = "%s (Default=%s)" % (val, default)493 ret.append(browser.MakeHLI(val, "Argument"))494 495 try:496 fkind = self.funckinds[fd[3]]497 except KeyError:498 fkind = "Unknown"499 ret.append(browser.MakeHLI(fkind, "Function Kind"))500 try:501 ikind = self.invokekinds[fd[4]]502 except KeyError:503 ikind = "Unknown"504 ret.append(browser.MakeHLI(ikind, "Invoke Kind"))505 # 5 = call conv506 # 5 = offset vtbl507 ret.append(browser.MakeHLI(fd[6], "Number Optional Params"))508 flagDescs = []509 for flag, desc in self.funcflags:510 if flag & fd[9]:511 flagDescs.append(desc)512 if flagDescs:513 ret.append(browser.MakeHLI(", ".join(flagDescs), "Function Flags"))514 return ret515 516 517HLITypeKinds = {518 pythoncom.TKIND_ENUM: (HLITypeLibEnum, "Enumeration"),519 pythoncom.TKIND_RECORD: (HLITypeLibEntry, "Record"),520 pythoncom.TKIND_MODULE: (HLITypeLibEnum, "Module"),521 pythoncom.TKIND_INTERFACE: (HLITypeLibMethod, "Interface"),522 pythoncom.TKIND_DISPATCH: (HLITypeLibMethod, "Dispatch"),523 pythoncom.TKIND_COCLASS: (HLICoClass, "CoClass"),524 pythoncom.TKIND_ALIAS: (HLITypeLibEntry, "Alias"),525 pythoncom.TKIND_UNION: (HLITypeLibEntry, "Union"),526}527 528 529class HLITypeLib(HLICOM):530 def GetSubList(self):531 ret = []532 ret.append(browser.MakeHLI(self.myobject, "Filename"))533 try:534 tlb = pythoncom.LoadTypeLib(self.myobject)535 except pythoncom.com_error:536 return [browser.MakeHLI("%s can not be loaded" % self.myobject)]537 538 for i in range(tlb.GetTypeInfoCount()):539 try:540 ret.append(HLITypeKinds[tlb.GetTypeInfoType(i)][0]((tlb, i)))541 except pythoncom.com_error:542 ret.append(browser.MakeHLI("The type info can not be loaded!"))543 ret.sort()544 return ret545 546 547class HLIHeadingRegisterdTypeLibs(HLICOM):548 "A tree heading for registered type libraries"549 550 def GetText(self):551 return "Registered Type Libraries"552 553 def GetSubList(self):554 # Explicit lookup in the registry.555 ret = []556 key = win32api.RegOpenKey(win32con.HKEY_CLASSES_ROOT, "TypeLib")557 win32ui.DoWaitCursor(1)558 try:559 num = 0560 while 1:561 try:562 keyName = win32api.RegEnumKey(key, num)563 except win32api.error:564 break565 # Enumerate all version info566 subKey = win32api.RegOpenKey(key, keyName)567 name = None568 try:569 subNum = 0570 bestVersion = 0.0571 while 1:572 try:573 versionStr = win32api.RegEnumKey(subKey, subNum)574 except win32api.error:575 break576 try:577 versionFlt = float(versionStr)578 except ValueError:579 versionFlt = 0 # ????580 if versionFlt > bestVersion:581 bestVersion = versionFlt582 name = win32api.RegQueryValue(subKey, versionStr)583 subNum = subNum + 1584 finally:585 win32api.RegCloseKey(subKey)586 if name is not None:587 ret.append(HLIRegisteredTypeLibrary((keyName, versionStr), name))588 num = num + 1589 finally:590 win32api.RegCloseKey(key)591 win32ui.DoWaitCursor(0)592 ret.sort()593 return ret594 595 596def main(modal=True, mdi=False):597 from pywin.tools import hierlist598 599 root = HLIRoot("COM Browser")600 if mdi and "pywin.framework.app" in sys.modules:601 # do it in a MDI window602 browser.MakeTemplate()603 browser.template.OpenObject(root)604 else:605 dlg = browser.dynamic_browser(root)606 if modal:607 dlg.DoModal()608 else:609 dlg.CreateWindow()610 dlg.ShowWindow()611 612 613if __name__ == "__main__":614 main(modal=win32api.GetConsoleTitle())615 616 ni = pythoncom._GetInterfaceCount()617 ng = pythoncom._GetGatewayCount()618 if ni or ng:619 print("Warning - exiting with %d/%d objects alive" % (ni, ng))620 