123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- import os
- import string
- import sys
-
- import pythoncom
- import win32api
- from win32com.axdebug import (
- adb,
- axdebug,
- codecontainer,
- contexts,
- documents,
- expressions,
- gateways,
- )
- from win32com.axdebug.util import _wrap, _wrap_remove, trace
- from win32com.axscript import axscript
-
- 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 "<ModuleTreeNode wrapping %s>" % (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())
- )
|