Kano001's picture
Upload 261 files
10865e1 verified
raw
history blame
7.32 kB
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())
)