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.

debugger.py 7.2KB

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