Spaces:
Running
Running
import sys | |
import pythoncom | |
import win32com.server.policy | |
from win32com.axscript import axscript | |
from win32com.axscript.server import axsite | |
from win32com.axscript.server.error import Exception | |
from win32com.server import connect, util | |
class MySite(axsite.AXSite): | |
def OnScriptError(self, error): | |
exc = error.GetExceptionInfo() | |
context, line, char = error.GetSourcePosition() | |
print(" >Exception:", exc[1]) | |
try: | |
st = error.GetSourceLineText() | |
except pythoncom.com_error: | |
st = None | |
if st is None: | |
st = "" | |
text = st + "\n" + (" " * (char - 1)) + "^" + "\n" + exc[2] | |
for line in text.splitlines(): | |
print(" >" + line) | |
class MyCollection(util.Collection): | |
def _NewEnum(self): | |
print("Making new Enumerator") | |
return util.Collection._NewEnum(self) | |
class Test: | |
_public_methods_ = ["echo"] | |
_public_attrs_ = ["collection", "verbose"] | |
def __init__(self): | |
self.verbose = 0 | |
self.collection = util.wrap(MyCollection([1, "Two", 3])) | |
self.last = "" | |
# self._connect_server_ = TestConnectServer(self) | |
def echo(self, *args): | |
self.last = "".join(map(str, args)) | |
if self.verbose: | |
for arg in args: | |
print(arg, end=" ") | |
print() | |
# self._connect_server_.Broadcast(last) | |
#### Connections currently wont work, as there is no way for the engine to | |
#### know what events we support. We need typeinfo support. | |
IID_ITestEvents = pythoncom.MakeIID("{8EB72F90-0D44-11d1-9C4B-00AA00125A98}") | |
class TestConnectServer(connect.ConnectableServer): | |
_connect_interfaces_ = [IID_ITestEvents] | |
# The single public method that the client can call on us | |
# (ie, as a normal COM server, this exposes just this single method. | |
def __init__(self, object): | |
self.object = object | |
def Broadcast(self, arg): | |
# Simply broadcast a notification. | |
self._BroadcastNotify(self.NotifyDoneIt, (arg,)) | |
def NotifyDoneIt(self, interface, arg): | |
interface.Invoke(1000, 0, pythoncom.DISPATCH_METHOD, 1, arg) | |
VBScript = """\ | |
prop = "Property Value" | |
sub hello(arg1) | |
test.echo arg1 | |
end sub | |
sub testcollection | |
test.verbose = 1 | |
for each item in test.collection | |
test.echo "Collection item is", item | |
next | |
end sub | |
""" | |
if sys.version_info < (3,): | |
PyScript = """print "PyScript is being parsed..."\n""" | |
else: | |
PyScript = """print("PyScript is being parsed...")\n""" | |
PyScript += """\ | |
prop = "Property Value" | |
def hello(arg1): | |
test.echo(arg1) | |
pass | |
def testcollection(): | |
test.verbose = 1 | |
# test.collection[1] = "New one" | |
for item in test.collection: | |
test.echo("Collection item is", item) | |
pass | |
""" | |
ErrScript = """\ | |
bad code for everyone! | |
""" | |
def TestEngine(engineName, code, bShouldWork=1): | |
echoer = Test() | |
model = { | |
"test": util.wrap(echoer), | |
} | |
site = MySite(model) | |
engine = site._AddEngine(engineName) | |
engine.AddCode(code, axscript.SCRIPTTEXT_ISPERSISTENT) | |
try: | |
engine.Start() | |
finally: | |
if not bShouldWork: | |
engine.Close() | |
return | |
doTestEngine(engine, echoer) | |
# re-transition the engine back to the UNINITIALIZED state, a-la ASP. | |
engine.eScript.SetScriptState(axscript.SCRIPTSTATE_UNINITIALIZED) | |
engine.eScript.SetScriptSite(util.wrap(site)) | |
print("restarting") | |
engine.Start() | |
# all done! | |
engine.Close() | |
def doTestEngine(engine, echoer): | |
# Now call into the scripts IDispatch | |
from win32com.client.dynamic import Dispatch | |
ob = Dispatch(engine.GetScriptDispatch()) | |
try: | |
ob.hello("Goober") | |
except pythoncom.com_error as exc: | |
print("***** Calling 'hello' failed", exc) | |
return | |
if echoer.last != "Goober": | |
print("***** Function call didnt set value correctly", repr(echoer.last)) | |
if str(ob.prop) != "Property Value": | |
print("***** Property Value not correct - ", repr(ob.prop)) | |
ob.testcollection() | |
# Now make sure my engines can evaluate stuff. | |
result = engine.eParse.ParseScriptText( | |
"1+1", None, None, None, 0, 0, axscript.SCRIPTTEXT_ISEXPRESSION | |
) | |
if result != 2: | |
print("Engine could not evaluate '1+1' - said the result was", result) | |
def dotestall(): | |
for i in range(10): | |
TestEngine("Python", PyScript) | |
print(sys.gettotalrefcount()) | |
## print "Testing Exceptions" | |
## try: | |
## TestEngine("Python", ErrScript, 0) | |
## except pythoncom.com_error: | |
## pass | |
def testall(): | |
dotestall() | |
pythoncom.CoUninitialize() | |
print( | |
"AXScript Host worked correctly - %d/%d COM objects left alive." | |
% (pythoncom._GetInterfaceCount(), pythoncom._GetGatewayCount()) | |
) | |
if __name__ == "__main__": | |
testall() | |