debugger.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import sys, traceback, string
  2. from win32com.axscript import axscript
  3. from win32com.axdebug import codecontainer, axdebug, gateways, documents, contexts, adb, expressions
  4. from win32com.axdebug.util import trace, _wrap, _wrap_remove
  5. import pythoncom
  6. import win32api, winerror
  7. import os
  8. currentDebugger = None
  9. class ModuleTreeNode:
  10. """Helper class for building a module tree
  11. """
  12. def __init__(self, module):
  13. modName = module.__name__
  14. self.moduleName = modName
  15. self.module = module
  16. self.realNode = None
  17. self.cont = codecontainer.SourceModuleContainer(module)
  18. def __repr__(self):
  19. return "<ModuleTreeNode wrapping %s>" % (self.module)
  20. def Attach(self, parentRealNode):
  21. self.realNode.Attach(parentRealNode)
  22. def Close(self):
  23. self.module = None
  24. self.cont = None
  25. self.realNode = None
  26. def BuildModule(module, built_nodes, rootNode, create_node_fn, create_node_args ):
  27. if module:
  28. keep = module.__name__
  29. keep = keep and (built_nodes.get(module) is None)
  30. if keep and hasattr(module, '__file__'):
  31. keep = string.lower(os.path.splitext(module.__file__)[1]) not in [".pyd", ".dll"]
  32. # keep = keep and module.__name__=='__main__'
  33. if module and keep:
  34. # print "keeping", module.__name__
  35. node = ModuleTreeNode(module)
  36. built_nodes[module] = node
  37. realNode = create_node_fn(*(node,)+create_node_args)
  38. node.realNode = realNode
  39. # Split into parent nodes.
  40. parts = string.split(module.__name__, '.')
  41. if parts[-1][:8]=='__init__': parts = parts[:-1]
  42. parent = string.join(parts[:-1], '.')
  43. parentNode = rootNode
  44. if parent:
  45. parentModule = sys.modules[parent]
  46. BuildModule(parentModule, built_nodes, rootNode, create_node_fn, create_node_args)
  47. if parentModule in built_nodes:
  48. parentNode = built_nodes[parentModule].realNode
  49. node.Attach(parentNode)
  50. def RefreshAllModules(builtItems, rootNode, create_node, create_node_args):
  51. for module in list(sys.modules.values()):
  52. BuildModule(module, builtItems, rootNode, create_node, create_node_args)
  53. # realNode = pdm.CreateDebugDocumentHelper(None) # DebugDocumentHelper node?
  54. # app.CreateApplicationNode() # doc provider node.
  55. class CodeContainerProvider(documents.CodeContainerProvider):
  56. def __init__(self, axdebugger):
  57. self.axdebugger = axdebugger
  58. documents.CodeContainerProvider.__init__(self)
  59. self.currentNumModules = len(sys.modules)
  60. self.nodes = {}
  61. self.axdebugger.RefreshAllModules(self.nodes, self)
  62. def FromFileName(self, fname):
  63. ### It appears we cant add modules during a debug session!
  64. # if self.currentNumModules != len(sys.modules):
  65. # self.axdebugger.RefreshAllModules(self.nodes, self)
  66. # self.currentNumModules = len(sys.modules)
  67. # for key in self.ccsAndNodes.keys():
  68. # print "File:", key
  69. return documents.CodeContainerProvider.FromFileName(self, fname)
  70. def Close(self):
  71. documents.CodeContainerProvider.Close(self)
  72. self.axdebugger = None
  73. print("Closing %d nodes" % (len(self.nodes)))
  74. for node in self.nodes.values():
  75. node.Close()
  76. self.nodes = {}
  77. class OriginalInterfaceMaker:
  78. def MakeInterfaces(self, pdm):
  79. app = self.pdm.CreateApplication()
  80. self.cookie = pdm.AddApplication(app)
  81. root = app.GetRootNode()
  82. return app, root
  83. def CloseInterfaces(self, pdm):
  84. pdm.RemoveApplication(self.cookie)
  85. class SimpleHostStyleInterfaceMaker:
  86. def MakeInterfaces(self, pdm):
  87. app = pdm.GetDefaultApplication()
  88. root = app.GetRootNode()
  89. return app, root
  90. def CloseInterfaces(self, pdm):
  91. pass
  92. class AXDebugger:
  93. def __init__(self, interfaceMaker = None, processName = None):
  94. if processName is None: processName = "Python Process"
  95. if interfaceMaker is None: interfaceMaker = SimpleHostStyleInterfaceMaker()
  96. self.pydebugger = adb.Debugger()
  97. self.pdm=pythoncom.CoCreateInstance(axdebug.CLSID_ProcessDebugManager,None,pythoncom.CLSCTX_ALL, axdebug.IID_IProcessDebugManager)
  98. self.app, self.root = interfaceMaker.MakeInterfaces(self.pdm)
  99. self.app.SetName(processName)
  100. self.interfaceMaker = interfaceMaker
  101. expressionProvider = _wrap(expressions.ProvideExpressionContexts(), axdebug.IID_IProvideExpressionContexts)
  102. self.expressionCookie = self.app.AddGlobalExpressionContextProvider(expressionProvider)
  103. contProvider = CodeContainerProvider(self)
  104. self.pydebugger.AttachApp(self.app, contProvider)
  105. def Break(self):
  106. # Get the frame we start debugging from - this is the frame 1 level up
  107. try:
  108. 1 + ''
  109. except:
  110. frame = sys.exc_info()[2].tb_frame.f_back
  111. # Get/create the debugger, and tell it to break.
  112. self.app.StartDebugSession()
  113. # self.app.CauseBreak()
  114. self.pydebugger.SetupAXDebugging(None, frame)
  115. self.pydebugger.set_trace()
  116. def Close(self):
  117. self.pydebugger.ResetAXDebugging()
  118. self.interfaceMaker.CloseInterfaces(self.pdm)
  119. self.pydebugger.CloseApp()
  120. self.app.RemoveGlobalExpressionContextProvider(self.expressionCookie)
  121. self.expressionCookie = None
  122. self.pdm = None
  123. self.app = None
  124. self.pydebugger = None
  125. self.root = None
  126. def RefreshAllModules(self, nodes, containerProvider):
  127. RefreshAllModules(nodes, self.root, self.CreateApplicationNode, (containerProvider,))
  128. def CreateApplicationNode(self, node, containerProvider):
  129. realNode = self.app.CreateApplicationNode()
  130. document = documents.DebugDocumentText(node.cont)
  131. document = _wrap(document, axdebug.IID_IDebugDocument)
  132. node.cont.debugDocument = document
  133. provider = documents.DebugDocumentProvider(document)
  134. provider = _wrap(provider, axdebug.IID_IDebugDocumentProvider)
  135. realNode.SetDocumentProvider(provider)
  136. containerProvider.AddCodeContainer(node.cont, realNode)
  137. return realNode
  138. def _GetCurrentDebugger():
  139. global currentDebugger
  140. if currentDebugger is None:
  141. currentDebugger = AXDebugger()
  142. return currentDebugger
  143. def Break():
  144. _GetCurrentDebugger().Break()
  145. brk = Break
  146. set_trace = Break
  147. def dosomethingelse():
  148. a=2
  149. b = "Hi there"
  150. def dosomething():
  151. a=1
  152. b=2
  153. dosomethingelse()
  154. def test():
  155. Break()
  156. input("Waiting...")
  157. dosomething()
  158. print("Done")
  159. if __name__=='__main__':
  160. print("About to test the debugging interfaces!")
  161. test()
  162. print(" %d/%d com objects still alive" % (pythoncom._GetInterfaceCount(), pythoncom._GetGatewayCount()))