import sys, traceback, string from win32com.axscript import axscript from win32com.axdebug import codecontainer, axdebug, gateways, documents, contexts, adb, expressions from win32com.axdebug.util import trace, _wrap, _wrap_remove import pythoncom import win32api, winerror import os currentDebugger = None class ModuleTreeNode: """Helper class for building a module tree """ def __init__(self, module): modName = module.__name__ self.moduleName = modName self.module = module self.realNode = None self.cont = codecontainer.SourceModuleContainer(module) def __repr__(self): return "" % (self.module) def Attach(self, parentRealNode): self.realNode.Attach(parentRealNode) def Close(self): self.module = None self.cont = None self.realNode = None def BuildModule(module, built_nodes, rootNode, create_node_fn, create_node_args ): if module: keep = module.__name__ keep = keep and (built_nodes.get(module) is None) if keep and hasattr(module, '__file__'): keep = string.lower(os.path.splitext(module.__file__)[1]) not in [".pyd", ".dll"] # keep = keep and module.__name__=='__main__' if module and keep: # print "keeping", module.__name__ node = ModuleTreeNode(module) built_nodes[module] = node realNode = create_node_fn(*(node,)+create_node_args) node.realNode = realNode # Split into parent nodes. parts = string.split(module.__name__, '.') if parts[-1][:8]=='__init__': parts = parts[:-1] parent = string.join(parts[:-1], '.') parentNode = rootNode if parent: parentModule = sys.modules[parent] BuildModule(parentModule, built_nodes, rootNode, create_node_fn, create_node_args) if parentModule in built_nodes: parentNode = built_nodes[parentModule].realNode node.Attach(parentNode) def RefreshAllModules(builtItems, rootNode, create_node, create_node_args): for module in list(sys.modules.values()): BuildModule(module, builtItems, rootNode, create_node, create_node_args) # realNode = pdm.CreateDebugDocumentHelper(None) # DebugDocumentHelper node? # app.CreateApplicationNode() # doc provider node. class CodeContainerProvider(documents.CodeContainerProvider): def __init__(self, axdebugger): self.axdebugger = axdebugger documents.CodeContainerProvider.__init__(self) self.currentNumModules = len(sys.modules) self.nodes = {} self.axdebugger.RefreshAllModules(self.nodes, self) def FromFileName(self, fname): ### It appears we cant add modules during a debug session! # if self.currentNumModules != len(sys.modules): # self.axdebugger.RefreshAllModules(self.nodes, self) # self.currentNumModules = len(sys.modules) # for key in self.ccsAndNodes.keys(): # print "File:", key return documents.CodeContainerProvider.FromFileName(self, fname) def Close(self): documents.CodeContainerProvider.Close(self) self.axdebugger = None print("Closing %d nodes" % (len(self.nodes))) for node in self.nodes.values(): node.Close() self.nodes = {} class OriginalInterfaceMaker: def MakeInterfaces(self, pdm): app = self.pdm.CreateApplication() self.cookie = pdm.AddApplication(app) root = app.GetRootNode() return app, root def CloseInterfaces(self, pdm): pdm.RemoveApplication(self.cookie) class SimpleHostStyleInterfaceMaker: def MakeInterfaces(self, pdm): app = pdm.GetDefaultApplication() root = app.GetRootNode() return app, root def CloseInterfaces(self, pdm): pass class AXDebugger: def __init__(self, interfaceMaker = None, processName = None): if processName is None: processName = "Python Process" if interfaceMaker is None: interfaceMaker = SimpleHostStyleInterfaceMaker() self.pydebugger = adb.Debugger() self.pdm=pythoncom.CoCreateInstance(axdebug.CLSID_ProcessDebugManager,None,pythoncom.CLSCTX_ALL, axdebug.IID_IProcessDebugManager) self.app, self.root = interfaceMaker.MakeInterfaces(self.pdm) self.app.SetName(processName) self.interfaceMaker = interfaceMaker expressionProvider = _wrap(expressions.ProvideExpressionContexts(), axdebug.IID_IProvideExpressionContexts) self.expressionCookie = self.app.AddGlobalExpressionContextProvider(expressionProvider) contProvider = CodeContainerProvider(self) self.pydebugger.AttachApp(self.app, contProvider) def Break(self): # Get the frame we start debugging from - this is the frame 1 level up try: 1 + '' except: frame = sys.exc_info()[2].tb_frame.f_back # Get/create the debugger, and tell it to break. self.app.StartDebugSession() # self.app.CauseBreak() self.pydebugger.SetupAXDebugging(None, frame) self.pydebugger.set_trace() def Close(self): self.pydebugger.ResetAXDebugging() self.interfaceMaker.CloseInterfaces(self.pdm) self.pydebugger.CloseApp() self.app.RemoveGlobalExpressionContextProvider(self.expressionCookie) self.expressionCookie = None self.pdm = None self.app = None self.pydebugger = None self.root = None def RefreshAllModules(self, nodes, containerProvider): RefreshAllModules(nodes, self.root, self.CreateApplicationNode, (containerProvider,)) def CreateApplicationNode(self, node, containerProvider): realNode = self.app.CreateApplicationNode() document = documents.DebugDocumentText(node.cont) document = _wrap(document, axdebug.IID_IDebugDocument) node.cont.debugDocument = document provider = documents.DebugDocumentProvider(document) provider = _wrap(provider, axdebug.IID_IDebugDocumentProvider) realNode.SetDocumentProvider(provider) containerProvider.AddCodeContainer(node.cont, realNode) return realNode def _GetCurrentDebugger(): global currentDebugger if currentDebugger is None: currentDebugger = AXDebugger() return currentDebugger def Break(): _GetCurrentDebugger().Break() brk = Break set_trace = Break def dosomethingelse(): a=2 b = "Hi there" def dosomething(): a=1 b=2 dosomethingelse() def test(): Break() input("Waiting...") dosomething() print("Done") if __name__=='__main__': print("About to test the debugging interfaces!") test() print(" %d/%d com objects still alive" % (pythoncom._GetInterfaceCount(), pythoncom._GetGatewayCount()))