Todo: 集成多平台 解决因SaiNiu线程抢占资源问题 本地提交测试环境打包 和 正式打包脚本与正式环境打包bat 提交Python32环境包 改进多日志文件生成情况修改打包日志细节
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
<HTML>
|
||||
|
||||
<SCRIPT Language="Python" RUNAT=Server>
|
||||
|
||||
# Just for the sake of the demo, our Python script engine
|
||||
# will create a Python.Interpreter COM object, and call that.
|
||||
|
||||
# This is completely useless, as the Python Script Engine is
|
||||
# completely normal Python, and ASP does not impose retrictions, so
|
||||
# there is nothing the COM object can do that we can not do natively.
|
||||
|
||||
o = Server.CreateObject("Python.Interpreter")
|
||||
|
||||
Response.Write("Python says 1+1=" + str(o.Eval("1+1")))
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
</HTML>
|
||||
@@ -0,0 +1,52 @@
|
||||
<%@ Language=Python %>
|
||||
<HTML>
|
||||
|
||||
<HEAD>
|
||||
|
||||
<BODY BACKGROUND="/samples/images/backgrnd.gif">
|
||||
|
||||
<TITLE>Python test</TITLE>
|
||||
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="FFFFFF">
|
||||
|
||||
<SCRIPT Language="Python" RUNAT=Server>
|
||||
# NOTE that the <% tags below execute _before_ these tags!
|
||||
Response.Write("Hello from Python<P>")
|
||||
Response.Write("Browser is "+bc.browser)
|
||||
import win32api # Should be no problem using win32api in ASP pages.
|
||||
Response.Write("<p>Win32 username is "+win32api.GetUserName())
|
||||
</SCRIPT>
|
||||
|
||||
<BODY BGCOLOR="FFFFFF">
|
||||
|
||||
<%
|
||||
import sys
|
||||
print(sys.path)
|
||||
from win32com.axscript.asputil import *
|
||||
print("Hello")
|
||||
print("There")
|
||||
print("How are you")
|
||||
%>
|
||||
|
||||
<%bc = Server.CreateObject("MSWC.BrowserType")%>
|
||||
<BODY BGCOLOR="FFFFFF">
|
||||
<table border=1>
|
||||
<tr><td>Browser</td><td> <%=bc.browser %>
|
||||
<tr><td>Version</td><td> <%=bc.version %> </td></TR>
|
||||
<tr><td>Frames</td><td>
|
||||
<%Response.Write( iif(bc.frames, "TRUE", "FALSE")) %></td></TR>
|
||||
<tr><td>Tables</td><td>
|
||||
<%Response.Write( iif (bc.tables, "TRUE", "FALSE")) %></td></TR>
|
||||
<tr><td>BackgroundSounds</td><td>
|
||||
<%Response.Write( iif(bc.BackgroundSounds, "TRUE", "FALSE"))%></td></TR>
|
||||
<tr><td>VBScript</td><td>
|
||||
<%Response.Write( iif(bc.vbscript, "TRUE", "FALSE"))%></td></TR>
|
||||
<tr><td>JavaScript</td><td>
|
||||
<%Response.Write( iif(bc.javascript, "TRUE", "FALSE"))%></td></TR>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,4 @@
|
||||
<%@ language=python%>
|
||||
<html>
|
||||
<%Response.Redirect("test1.html")%>
|
||||
</html>
|
||||
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<body>
|
||||
GOT There
|
||||
<script language=javascript>
|
||||
location.href ="http://192.168.0.1/Python/interrupt/test.asp"
|
||||
</script>
|
||||
</body>
|
||||
</head>
|
||||
</html>
|
||||
@@ -0,0 +1,6 @@
|
||||
<%@ language =Python%>
|
||||
<html>
|
||||
<head>
|
||||
<%Response.Redirect("test.html")%>
|
||||
</head>
|
||||
</html>
|
||||
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<body>
|
||||
GOT HERE
|
||||
<script language=javascript>
|
||||
location.href ="http://192.168.0.1/Python/interrupt/test1.asp"
|
||||
</script>
|
||||
</body>
|
||||
</head>
|
||||
</html>
|
||||
@@ -0,0 +1,10 @@
|
||||
<HTML>
|
||||
|
||||
<SCRIPT Language="Python" RUNAT=Server>
|
||||
|
||||
for i in range(3,8):
|
||||
Response.Write("<FONT SIZE=%d>Hello World!!<BR>" % i)
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
</HTML>
|
||||
@@ -0,0 +1,179 @@
|
||||
<!--
|
||||
original Author: Bill Rollins
|
||||
adapted for python by aaron watters
|
||||
Purpose: This HTML example shows how to use Microsoft's ActiveX Chart control.
|
||||
Properties of the control are changed using sub procedures called
|
||||
by radio buttons and check boxes. The AboutBox method is called from
|
||||
a command button.
|
||||
Created: 3/16/96
|
||||
Edited: 3/19/96 - VBScript code edited so there is only one procedure for each property.
|
||||
3/23/96 - Font sizes changed in title. Added text to the Notes section.
|
||||
6/01/96 - Change OBJECT tag to match E3 Beta requirements
|
||||
-->
|
||||
|
||||
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>ActiveX / VBScript Chart Example</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR=#FFFFCC TEXT=#000000>
|
||||
|
||||
<B><FONT SIZE=6>Chart Example</FONT></B><BR>
|
||||
<FONT SIZE=2>You must be running Microsoft Internet Explorer 3.0 and have the Microsoft ActiveX Chart Control installed to view this page.</FONT><BR>
|
||||
<P>
|
||||
The chart control enables you to draw charts. The chart's types and styles are properties of the control. The chart has one method, AboutBox. The chart generates no events.
|
||||
|
||||
<HR>
|
||||
|
||||
<OBJECT
|
||||
classid="clsid:FC25B780-75BE-11CF-8B01-444553540000"
|
||||
CODEBASE="http://activex.microsoft.com/controls/iexplorer/iechart.ocx#Version=4,70,0,1161"
|
||||
TYPE="application/x-oleobject"
|
||||
id=Chart1
|
||||
width=200
|
||||
height=200
|
||||
align=left
|
||||
hspace=0
|
||||
vspace=0
|
||||
>
|
||||
|
||||
<param name="_extentX" value="300">
|
||||
<param name="_extentY" value="150">
|
||||
<param name="ChartStyle" value="0">
|
||||
<param name="ChartType" value="4">
|
||||
<param name="hgridStyle" value="0">
|
||||
<param name="vgridStyle" value="0">
|
||||
<param name="colorscheme" value="0">
|
||||
<param name="rows" value="2">
|
||||
<param name="columns" value="4">
|
||||
<param name="data[0][0]" value="30">
|
||||
<param name="data[0][1]" value="2">
|
||||
<param name="data[0][2]" value="20">
|
||||
<param name="data[0][3]" value="40">
|
||||
<param name="data[1][0]" value="15">
|
||||
<param name="data[1][1]" value="33">
|
||||
<param name="data[1][2]" value="21">
|
||||
<param name="data[1][3]" value="45">
|
||||
<param name="BackStyle" value="1">
|
||||
|
||||
|
||||
</object>
|
||||
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
|
||||
|
||||
# Calls the AboutBox Method. This displays the Chart Object About Box
|
||||
def DoChartAboutBox():
|
||||
ax.Chart1.AboutBox()
|
||||
|
||||
# Changes the type of chart. WhatType is passed as a value (0-5) when one of the Chart Type radio buttons is selected
|
||||
def DoChartType(WhatType):
|
||||
ax.Chart1.ChartType = WhatType
|
||||
|
||||
# Turns horizontal gridlines on or off depending on value of chkHorizontal checkbox
|
||||
def DoHorizontalGrid():
|
||||
print(ax.chkHorizontal.Checked)
|
||||
if ax.chkHorizontal.Checked:
|
||||
ax.Chart1.HGridStyle = 1
|
||||
else:
|
||||
ax.Chart1.HGridStyle = 0
|
||||
|
||||
# Sets the background of the chart to Opaque or Transparent
|
||||
def DoBackground(intBackGround):
|
||||
ax.Chart1.BackStyle = intBackGround
|
||||
|
||||
# Turns vertical gridlines on or off depending on value of chkVertical checkbox
|
||||
def DoVerticalGrid():
|
||||
if ax.chkVertical.Checked:
|
||||
ax.Chart1.VGridStyle = 1
|
||||
else:
|
||||
ax.Chart1.VGridStyle = 0
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
|
||||
|
||||
<TABLE BORDER = 0 XBORDER=5 BGCOLOR="#FFFFCC" WIDTH=300 ALIGN=LEFT>
|
||||
<TR><TD colspan=2 BGCOLOR=NAVY ALIGN=CENTER><FONT COLOR=FFFFCC>Chart Type</TR>
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(0)"> Simple Pie </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(11)"> Simple Column </TD></TR>
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(1)"> Pie with Wedge Out </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(12)"> Stacked Column </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(2)"> Simple Point </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(13)"> Full Column </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(3)"> Stacked Point </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(14)"> Simple Bar </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(4)"> Full Point </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(15)"> Stacked Bar </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(5)"> Simple Line </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(16)"> Full Bar </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(6)"> Stacked Line </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(17)"> HLC Stock </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(7)"> Full Line </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(18)"> HLC Stock WSJ</TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(8)"> Simple Area </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(19)"> OHLC Stock </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(9)"> Stack Area </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(20)"> OHLC Stock WSJ </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(10)"> Full Area </TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<TABLE XBORDER=5 WIDTH=125 BGCOLOR="#FFFFCC" ALIGN=LEFT>
|
||||
<TR><TD BGCOLOR=NAVY ALIGN=CENTER><FONT COLOR=FFFFCC>Gridlines</TR>
|
||||
<TR><TD><INPUT TYPE=CHECKBOX NAME="chkHorizontal" onClick="DoHorizontalGrid()">Horizontal</TD></TR>
|
||||
<TR><TD><INPUT TYPE=CHECKBOX NAME="chkVertical" onClick="DoVerticalGrid()">Vertical</TD></TR>
|
||||
<TR><TD BGCOLOR=NAVY ALIGN=CENTER><FONT COLOR=FFFFCC>Background</TR>
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=BackStyle onClick="DoBackground(1)">Opaque</TD></TR>
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=BackStyle onClick="DoBackground(0)">Transparent</TD></TR>
|
||||
|
||||
</TABLE>
|
||||
|
||||
<BR CLEAR=ALL>
|
||||
<BR>
|
||||
|
||||
<INPUT TYPE=BUTTON VALUE="About Chart Control" NAME="cdmChartAboutBox" onClick="DoChartAboutBox()">
|
||||
|
||||
<BR CLEAR=ALL>
|
||||
<BR><BR>
|
||||
|
||||
<HR>
|
||||
<B><FONT SIZE=4>Notes</FONT></B><BR>
|
||||
The chart's properties on this page are changed by selecting the various radio buttons and check boxes. The OnClick event of these intrinsic controls calls VBScript procedures that change the chart properties.<BR>
|
||||
<P>
|
||||
The About Chart Control command button calls the chart's AboutBox method.<BR>
|
||||
<P>
|
||||
To view the source code for this page, select <SAMP>Source</SAMP> from the <SAMP>View</SAMP> menu.<BR>
|
||||
<P>
|
||||
If you have any questions or comments about this example, please send them to <A HREF ="mailto:billr@smart.net">billr@smart.net</A>. We would appreciate feedback and would like to hear about other developers' experiences with these new tools.<BR>
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
</BODY>
|
||||
|
||||
|
||||
|
||||
<ADDRESS>
|
||||
<FONT SIZE=2>
|
||||
© 1996 Rollins & Associates, Inc.<BR>
|
||||
Page last updated 08/28/96<BR>
|
||||
Please send comments to <A HREF ="mailto:billr@smart.net">billr@smart.net</A><BR>
|
||||
</FONT>
|
||||
</ADDRESS>
|
||||
|
||||
</HTML>
|
||||
@@ -0,0 +1,46 @@
|
||||
<HTML>
|
||||
<BODY>
|
||||
Let's try this out:
|
||||
|
||||
<FORM>
|
||||
<INPUT NAME="Button1" TYPE="Button" OnClick="foo1" LANGUAGE="VBScript">
|
||||
<FORM METHOD="GET" NAME="MyForm">
|
||||
<INPUT TYPE="TEXT" NAME="Text1" SIZE=25>
|
||||
<INPUT TYPE="SUBMIT">
|
||||
<INPUT NAME="Button2" TYPE="Button" VALUE="Hi" OnClick="text2.value=window.document.location" LANGUAGE="VBScript">
|
||||
<INPUT TYPE="TEXT" SIZE=25 NAME="Text2">
|
||||
</FORM>
|
||||
And here is a second form
|
||||
<P>
|
||||
<FORM NAME="Form2" METHOD="GET">
|
||||
<INPUT NAME="Button2" TYPE="Button" VALUE="Hi" OnClick="button2.value=window.document.location" LANGUAGE="VBScript">
|
||||
</FORM><BR>
|
||||
|
||||
<SCRIPT LANGUAGE="JScript">
|
||||
y=15
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="VBScript">
|
||||
x = 13
|
||||
Sub foo1
|
||||
Dim y
|
||||
y = 14
|
||||
alert "Hello"
|
||||
End Sub
|
||||
|
||||
Sub Window_OnLoad
|
||||
foo1
|
||||
MyForm.button2.value = "Loaded"
|
||||
Form2.button2.value = "Loaded"
|
||||
End Sub
|
||||
Sub Link_MouseMove(b, s, x, y)
|
||||
MsgBox b
|
||||
End Sub
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
print("Python loaded")
|
||||
</SCRIPT>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -0,0 +1,24 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<base target="text">
|
||||
<TITLE> Internet Workshop </TITLE>
|
||||
</HEAD>
|
||||
<BODY leftmargin=8 bgcolor="#FFFFFF" VLINK="#666666" LINK="#FF0000">
|
||||
<FONT FACE="ARIAL,HELVETICA" SIZE="2">
|
||||
|
||||
<P>
|
||||
<BR>
|
||||
<P><FONT FACE="ARIAL,HELVETICA" SIZE="5"><B>Python AX Script Engine</B></FONT>
|
||||
<BR>Demo using the Marquee Control
|
||||
<BR>Mark Hammond.
|
||||
|
||||
<P>This is really quite a boring demo, as the Marquee control does everything. However, there is Python code behind the buttons that change the speed. This code is all of 2 lines per button!!!
|
||||
|
||||
<P>For more information on Python as an ActiveX scripting language, see
|
||||
|
||||
<P><B>Python</B>
|
||||
<BR><A HREF="https://www.python.org">https://www.python.org</A>
|
||||
|
||||
</FONT>
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -0,0 +1,115 @@
|
||||
<HTML>
|
||||
<HEAD><TITLE>Python Script sample: Calculator</TITLE></HEAD>
|
||||
<BODY><FONT FACE=ARIAL SIZE=3> <!-- global default -->
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
# globals
|
||||
Accum = 0.0 # Previous number (operand) awaiting operation
|
||||
FlagNewNum = 1 # Flag to indicate a new number (operand) is being entered
|
||||
NullOp = lambda x,y: y
|
||||
PendingOp = NullOp# Pending operation waiting for completion of second operand
|
||||
numberButNames = ['Zero','One','Two','Three','Four','Five','Six','Seven','Eight','Nine']
|
||||
|
||||
def NumPressed(Num):
|
||||
print("NumPressed", Num)
|
||||
global FlagNewNum
|
||||
if FlagNewNum:
|
||||
ax.document.Keypad.ReadOut.Value = Num
|
||||
FlagNewNum = None
|
||||
else:
|
||||
if ax.document.Keypad.ReadOut.Value == "0":
|
||||
ax.document.Keypad.ReadOut.Value = str(Num)
|
||||
else:
|
||||
ax.document.Keypad.ReadOut.Value= ax.document.Keypad.ReadOut.Value + str(Num)
|
||||
|
||||
# Dynamically create handlers for all the decimal buttons.
|
||||
# (ie, this will dynamically create "One_OnClick()"... etc handlers
|
||||
for i in range(len(numberButNames)):
|
||||
exec "def %s_OnClick():\tNumPressed(%d)\n" % (numberButNames[i],i)
|
||||
|
||||
def Decimal_OnClick():
|
||||
global curReadOut, FlagNewNum
|
||||
curReadOut = ax.document.Keypad.ReadOut.Value
|
||||
if FlagNewNum:
|
||||
curReadOut = "0."
|
||||
FlagNewNum = None
|
||||
else:
|
||||
if not ("." in curReadOut):
|
||||
curReadOut = curReadOut + "."
|
||||
ax.document.Keypad.ReadOut.Value = curReadOut
|
||||
|
||||
import sys, string
|
||||
|
||||
def Operation(Op, fn):
|
||||
global FlagNewNum, PendingOp, Accum
|
||||
ReadOut = ax.document.Keypad.ReadOut.Value
|
||||
print("Operation", Op, ReadOut, PendingOp, Accum)
|
||||
if FlagNewNum:
|
||||
# User is hitting op keys repeatedly, so don't do anything
|
||||
PendingOp = NullOp
|
||||
else:
|
||||
FlagNewNum = 1
|
||||
Accum = PendingOp( Accum, float(ReadOut) )
|
||||
ax.document.Keypad.ReadOut.Value = str(Accum)
|
||||
PendingOp = fn
|
||||
|
||||
def ClearEntry_OnClick():
|
||||
# Remove current number and reset state
|
||||
global FlagNewNum
|
||||
ax.document.Keypad.ReadOut.Value = "0"
|
||||
FlagNewNum = 1
|
||||
|
||||
def Clear_OnClick():
|
||||
global Accum, PendingOp
|
||||
Accum = 0
|
||||
PendingOp = NullOp
|
||||
ClearEntry_OnClick()
|
||||
|
||||
def Neg_OnClick():
|
||||
ax.document.Keypad.ReadOut.Value = str(-float(ax.document.Keypad.ReadOut.Value))
|
||||
</SCRIPT>
|
||||
|
||||
|
||||
<form action="" Name="Keypad">
|
||||
<TABLE>
|
||||
<B>
|
||||
<TABLE BORDER=2 WIDTH=50 HEIGHT=60 CELLPADDING=1 CELLSPACING=5>
|
||||
<CAPTION ALIGN=top> <b>Calculator</b><p> </CAPTION>
|
||||
<TR>
|
||||
<TD COLSPAN=3 ALIGN=MIDDLE><INPUT NAME="ReadOut" TYPE="Text" SIZE=24 VALUE="0" WIDTH=100%></TD>
|
||||
<TD></TD>
|
||||
<TD><INPUT NAME="Clear" TYPE="Button" VALUE=" C " ></TD>
|
||||
<TD><INPUT NAME="ClearEntry" TYPE="Button" VALUE=" CE " ></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><INPUT NAME="Seven" TYPE="Button" VALUE=" 7 " ></TD>
|
||||
<TD><INPUT NAME="Eight" TYPE="Button" VALUE=" 8 " ></TD>
|
||||
<TD><INPUT NAME="Nine" TYPE="Button" VALUE=" 9 " ></TD>
|
||||
<TD></TD>
|
||||
<TD><INPUT NAME="Neg" TYPE="Button" VALUE=" +/- " ></TD>
|
||||
<TD><INPUT NAME="Percent" TYPE="Button" VALUE=" % " OnClick="Operation('%', lambda x,y: x*y/100.0)"></TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><INPUT NAME="Four" TYPE="Button" VALUE=" 4 " ></TD>
|
||||
<TD><INPUT NAME="Five" TYPE="Button" VALUE=" 5 " ></TD>
|
||||
<TD><INPUT NAME="Six" TYPE="Button" VALUE=" 6 " ></TD>
|
||||
<TD></TD>
|
||||
<TD ALIGN=MIDDLE><INPUT NAME="Plus" TYPE="Button" VALUE=" + " OnClick="Operation('+', lambda x,y: x+y)"></TD>
|
||||
<TD ALIGN=MIDDLE><INPUT NAME="Minus" TYPE="Button" VALUE=" - " OnClick="Operation('-', lambda x,y: x-y)"></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><INPUT NAME="One" TYPE="Button" VALUE=" 1 " ></TD>
|
||||
<TD><INPUT NAME="Two" TYPE="Button" VALUE=" 2 " ></TD>
|
||||
<TD><INPUT NAME="Three" TYPE="Button" VALUE=" 3 " ></TD>
|
||||
<TD></TD>
|
||||
<TD ALIGN=MIDDLE><INPUT NAME="Multiply" TYPE="Button" VALUE=" * " OnClick="Operation('*', lambda x,y: x*y)" ></TD>
|
||||
<TD ALIGN=MIDDLE><INPUT NAME="Divide" TYPE="Button" VALUE=" / " OnClick="Operation('/', lambda x,y: x/y)" ></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><INPUT NAME="Zero" TYPE="Button" VALUE=" 0 " ></TD>
|
||||
<TD><INPUT NAME="Decimal" TYPE="Button" VALUE=" . " ></TD>
|
||||
<TD COLSPAN=3></TD>
|
||||
<TD><INPUT NAME="Equals" TYPE="Button" VALUE=" = " OnClick="Operation('=', lambda x,y: x)"></TD>
|
||||
</TR></TABLE></TABLE></B>
|
||||
</FORM>
|
||||
</FONT></BODY></HTML>
|
||||
@@ -0,0 +1,16 @@
|
||||
<HTML>
|
||||
<BODY>
|
||||
|
||||
<SCRIPT>
|
||||
b="Hello There, how are you"
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
print("Hello")
|
||||
a="Hi there"
|
||||
document.write("Hello<P>")
|
||||
alert("Hi there")
|
||||
</SCRIPT>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -0,0 +1,25 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Python AXScript Demos</TITLE>
|
||||
</HEAD>
|
||||
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
def Window_OnLoad():
|
||||
pass
|
||||
# import win32traceutil
|
||||
# print("Frames are", ax.window.frames._print_details_())
|
||||
# print("Frame 0 href = ", ax.frames.Item(0).location.href)
|
||||
|
||||
def Name_OnLoad():
|
||||
print("Frame loading")
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
<FRAMESET FRAMEBORDER=1 COLS = "250, *">
|
||||
<FRAME SRC="demo_menu.htm">
|
||||
<FRAME SRC="demo_check.htm" NAME="Body">
|
||||
</FRAMESET>
|
||||
|
||||
|
||||
</HTML>
|
||||
@@ -0,0 +1,39 @@
|
||||
<HTML>
|
||||
<H1>Engine Registration</H1>
|
||||
|
||||
<BODY>
|
||||
|
||||
<p>The Python ActiveX Scripting Engine is not currently registered.<p>
|
||||
|
||||
<p>Due to a <a href="https://web.archive.org/web/20080305234321/http://starship.python.net:80/crew/mhammond/win32/PrivacyProblem.html">
|
||||
privacy concern</a> discovered in the engine, the use of Python inside IE has been disabled.</p>
|
||||
|
||||
Before any of the supplied demos will work, the engine must be successfully registered.
|
||||
|
||||
<P>To install a version of the engine, that does work with IE, you can execute the Python program
|
||||
<CODE>win32com\axscript\client\pyscript_rexec.py</CODE> must be run. You can either do this manually, or follow the instructions below.</p>
|
||||
|
||||
<H2>Register the engine now!</H2>
|
||||
|
||||
<p>If you have read about the <a href="https://web.archive.org/web/20080305234321/http://starship.python.net:80/crew/mhammond/win32/PrivacyProblem.html">
|
||||
privacy concern</a> and still wish to register the engine, just follow the process outlined below:</p>
|
||||
<OL>
|
||||
<LI>Click on the link below
|
||||
<LI><B>A dialog will be presented asking if the file should be opened or saved to disk. Select "Open it".</B>
|
||||
<LI>A Console program will briefly open, while the server is registered.
|
||||
</OL>
|
||||
|
||||
<P><A HREF="..\..\..\client\pyscript_rexec.py">Register the engine now</A>
|
||||
|
||||
<H2>Checking the registration</H2>
|
||||
After the registration is complete, simply hit the Reload button. If the
|
||||
registration was successful, the page will change to the Python/AvtiveX Demo Page.
|
||||
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
try:
|
||||
window.open("demo_intro.htm", "Body")
|
||||
except:
|
||||
history.back()
|
||||
</SCRIPT>
|
||||
</BODY></HTML>
|
||||
@@ -0,0 +1,37 @@
|
||||
<HTML>
|
||||
<BODY>
|
||||
|
||||
<H1>
|
||||
<MARQUEE NAME="Marquee1" DIRECTION=LEFT BEHAVIOR=SCROLL SCROLLAMOUNT=10 SCROLLDELAY=200
|
||||
>Python ActiveX Scripting Demonstation
|
||||
</MARQUEE>
|
||||
</H1>
|
||||
|
||||
<p>Congratulations on installing the Python ActiveX Scripting Engine</p>
|
||||
|
||||
<p>Be warned that there is a <a href="https://web.archive.org/web/20080305234321/http://starship.python.net:80/crew/mhammond/win32/PrivacyProblem.html">
|
||||
privacy concern</a> with this engine. Please read this information, including how to disable the feature.</p>
|
||||
|
||||
|
||||
<H3>Object model</H3>
|
||||
<P>Except as described below, the object module exposed should be similar to that exposed
|
||||
by Visual Basic, etc. Due to the nature of ActiveX Scripting, the details for each
|
||||
host are different, but Python should work "correctly".
|
||||
|
||||
<P>The object model exposed via Python for MSIE is not as seamless as VB. The biggest limitation is
|
||||
the concept of a "local" namespace. For example, in VB, you can
|
||||
code <code>text="Hi there"</code>, but in Python, you must code
|
||||
<code>MyForm.ThisButton.Text="Hi There"</code>. See the <A HREF="foo2.htm">foo2</A> sample
|
||||
for futher details.
|
||||
|
||||
<H3>Known bugs and problems</H3>
|
||||
<UL>
|
||||
<LI><P>This release seems to have broken Aaron's mouse-trace sample. No idea why, and I'm supposed to be looking into it.
|
||||
<LI><P>Builtin objects such as MARQUEE are giving me grief. Objects accessed via forms are generally
|
||||
no problem.
|
||||
<LI><P>If you are trying to use Python with the Windows Scripting Host, note that
|
||||
.pys files are not correct registered - you will need to explicitly
|
||||
specify either cscript.exe or wscript.exe on the command line.
|
||||
</UL>
|
||||
|
||||
</BODY></HTML>
|
||||
@@ -0,0 +1,14 @@
|
||||
<HTML>
|
||||
<BODY>
|
||||
<H1>Scripting Demos</H1>
|
||||
<P>An <A HREF="demo_check.htm" TARGET=Body>Introduction</A> to the
|
||||
scripting engine.
|
||||
|
||||
<P>The <A HREF="calc.htm" TARGET=Body>Calculator Demo</A> is a very
|
||||
cool sample written by Aaron Watters.
|
||||
|
||||
<P><A HREF="mouseTrack.htm" TARGET=Body>Mouse track</A> is another of
|
||||
Aaron's samples, and shows how fast the Python engine is!
|
||||
|
||||
<P>The <A HREF="foo2.htm" TARGET=Body>foo2 sample</A> is mainly used
|
||||
for debugging and testing, but does show some forms in action.
|
||||
@@ -0,0 +1,25 @@
|
||||
<HTML>
|
||||
<BODY>
|
||||
A page generated by Python
|
||||
|
||||
<SCRIPT LANGUAGE="XXXVBScript">
|
||||
document.open()
|
||||
document.writeLn "<P>Hello from VBScript"
|
||||
document.close()
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
ax.document.write("<P>Hello from Python")
|
||||
ax.document.close()
|
||||
ax.document.open()
|
||||
ax.document.write("<P>Hello again from Python")
|
||||
ax.document.close()
|
||||
|
||||
def Window_OnLoad():
|
||||
pass
|
||||
# ax.document.write("<P>Hello from Load from Python")
|
||||
# ax.document.close()
|
||||
</SCRIPT>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -0,0 +1,105 @@
|
||||
<HTML>
|
||||
<BODY>
|
||||
|
||||
<SCRIPT>
|
||||
b="Hello"
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
import win32traceutil
|
||||
import sys
|
||||
print("Hello")
|
||||
a="Hi there"
|
||||
print("Location is", document.location)
|
||||
document.write("Hello", " from version ", 2, " of the Python AXScript Engine","<P>")
|
||||
document.writeln("This is Python", sys.version)
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
<P>The caption on the first button is set by the Window Load code. Clicking
|
||||
that button changes the text in the first edit box.
|
||||
|
||||
<P>The second button changes its own text when clicked.
|
||||
|
||||
<P>The fourth button calls a global function, defined in the global 'script' scope,
|
||||
rather than the 'MyForm' scope.
|
||||
|
||||
<FORM NAME="MyForm" METHOD="GET">
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
print("Hello from in the form")
|
||||
</SCRIPT>
|
||||
<INPUT NAME="Button1" TYPE="Button" OnClick="MyForm.Text1.value='Hi'" LANGUAGE="Python">
|
||||
<INPUT TYPE="TEXT" SIZE=25 NAME="Text1">
|
||||
<INPUT NAME="Button2" TYPE="Button" VALUE="Click for 'Hi'" OnClick="a='Howdy'; MyForm.Button2.value='Hi'" LANGUAGE="Python">
|
||||
<INPUT NAME="Button3" TYPE="Button" VALUE="Click for URL" OnClick="MyForm.Text2.value=document.location" LANGUAGE="Python">
|
||||
<INPUT TYPE="TEXT" SIZE=25 NAME="Text2">
|
||||
<INPUT NAME="Button4" TYPE="Button" VALUE="Call global fn" OnClick="foo1()" LANGUAGE="Python">
|
||||
<INPUT NAME="Button5" TYPE="Button" VALUE="Script for... Test">
|
||||
<script for="Button5" event="onClick" language="Python">
|
||||
print("HelloThere")
|
||||
window.alert("Hello")
|
||||
def ATest():
|
||||
print("Hello from ATEst")
|
||||
|
||||
ATest()
|
||||
</script>
|
||||
<INPUT NAME="Button6" TYPE="Button" VALUE="Set Other" OnClick="Form2.Text1.Value='Hi from other'" LANGUAGE="Python">
|
||||
|
||||
</FORM><BR>
|
||||
<P>
|
||||
And here is a second form
|
||||
<P>
|
||||
<FORM NAME="Form2" METHOD="GET">
|
||||
<INPUT NAME="Button1" TYPE="Button" OnClick="Form2.Text1.Value='Hi'" LANGUAGE="Python">
|
||||
<INPUT NAME="Button2" TYPE="Button" VALUE="Set Other" OnClick="MyForm.Text1.Value='Hi from other'" LANGUAGE="Python">
|
||||
<INPUT TYPE="TEXT" SIZE=25 NAME="Text1">
|
||||
<INPUT NAME="ButRExec" TYPE="Button" VALUE="RExec fail" OnClick="import win32api;win32api.MessageBox(0,'Oops')" LANGUAGE="Python">
|
||||
<INPUT NAME="ButRExec2" TYPE="Button" VALUE="RExec fail 2" OnClick="import sys,win32traceutil;print(sys.modules);from win32com.client import dynamic;import win32com.client.dynamic, pythoncom, win32com.client;o=win32com.client.Dispatch('Word.Application')" LANGUAGE="Python">
|
||||
<INPUT NAME="ButVB" TYPE="Button" VALUE="VBScript Button" OnClick='alert("Hi from VBScript")'>
|
||||
<INPUT NAME="ButCallChain" TYPE="Button" VALUE="Multi-Language call" OnClick='CallPython()'>
|
||||
</FORM><BR>
|
||||
|
||||
<SCRIPT LANGUAGE="VBScript">
|
||||
function CallPython()
|
||||
alert("Hello from VB - I'm about to call Python!")
|
||||
PythonGlobalFunction()
|
||||
end function
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="JScript">
|
||||
function JScriptFunction()
|
||||
{
|
||||
alert("Hello from JScript");
|
||||
}
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
x=13
|
||||
|
||||
def foo1():
|
||||
y = 14
|
||||
for name, item in globals().items():
|
||||
print(name, "item")
|
||||
alert ("Hello from AXCode")
|
||||
print("Y is ", y)
|
||||
|
||||
def PythonGlobalFunction():
|
||||
window.alert("Hello from Python - I'm about to call JScript!")
|
||||
window.JScriptFunction()
|
||||
|
||||
def Window_OnLoad():
|
||||
print("X is", x)
|
||||
print("a is", a)
|
||||
# print("------ GLOBALS ----------")
|
||||
# for n,v in globals().items():
|
||||
# print(n, '=', v)
|
||||
print("MyForm is", MyForm)
|
||||
print("MyForm is repr", "MyForm")
|
||||
print("MyForm.Button1 is", "MyForm.Button1")
|
||||
MyForm.Button1.Value = "Python Rules!"
|
||||
Form2.Button1.value = "Form2!"
|
||||
MyForm.Text1.value = document.location
|
||||
</SCRIPT>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -0,0 +1,25 @@
|
||||
<HTML>
|
||||
<BODY>
|
||||
|
||||
<FORM NAME="TestForm" METHOD="POST" >
|
||||
<INPUT TYPE="TEXT" SIZE=25 NAME="Name">Name<br>
|
||||
<INPUT TYPE="TEXT" SIZE=25 NAME="Address">Address<br>
|
||||
<INPUT TYPE=SUBMIT
|
||||
</FORM>
|
||||
|
||||
<SCRIPT LANGUAGE="Python" for="TestForm" Event="onSubmit">
|
||||
return Validate()
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
|
||||
def Validate():
|
||||
if not TestForm.Name.Value or not TestForm.Address.Value:
|
||||
ax.alert("You must enter a name and address.")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -0,0 +1,59 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<base target="text">
|
||||
<TITLE> Internet Workshop </TITLE>
|
||||
</HEAD>
|
||||
<BODY leftmargin=8 bgcolor="#FFFFFF" VLINK="#666666" LINK="#FF0000">
|
||||
<FONT FACE="ARIAL,HELVETICA" SIZE="2">
|
||||
|
||||
<P>
|
||||
<BR>
|
||||
<P><FONT FACE="ARIAL,HELVETICA" SIZE="5"><B>Marquee Demo</B></FONT>
|
||||
|
||||
<P>
|
||||
|
||||
|
||||
<OBJECT
|
||||
ID="Marquee1"
|
||||
CLASSID="CLSID:1A4DA620-6217-11CF-BE62-0080C72EDD2D"
|
||||
CODEBASE="/workshop/activex/gallery/ms/marquee/other/marquee.ocx#Version=4,70,0,1112"
|
||||
TYPE="application/x-oleobject"
|
||||
WIDTH=100%
|
||||
HEIGHT=80
|
||||
>
|
||||
<PARAM NAME="szURL" VALUE="marqueeText1.htm">
|
||||
<PARAM NAME="ScrollPixelsX" VALUE="0">
|
||||
<PARAM NAME="ScrollPixelsY" VALUE="-5">
|
||||
<PARAM NAME="ScrollDelay" VALUE="100">
|
||||
<PARAM NAME="Whitespace" VALUE="0">
|
||||
</OBJECT>
|
||||
|
||||
<br> <br>
|
||||
|
||||
<INPUT TYPE="Button" NAME="btnFaster" VALUE="Faster">
|
||||
<INPUT TYPE="Button" NAME="btnNormal" VALUE="Normal">
|
||||
<INPUT TYPE="Button" NAME="btnSlower" VALUE="Slower">
|
||||
|
||||
<SCRIPT Language="Python">
|
||||
|
||||
def btnFaster_Onclick():
|
||||
ax.Marquee1.ScrollDelay = 0
|
||||
|
||||
def btnNormal_Onclick():
|
||||
ax.Marquee1.ScrollDelay = 50
|
||||
|
||||
def btnSlower_Onclick():
|
||||
ax.Marquee1.ScrollDelay = 300
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
|
||||
<P>
|
||||
<HR>
|
||||
<B>Notes:</B>
|
||||
<P>
|
||||
|
||||
|
||||
</FONT>
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -0,0 +1,82 @@
|
||||
<HTML>
|
||||
|
||||
<HEAD><TITLE>Python Scripting sample: Mouse tracking</TITLE></HEAD>
|
||||
<BODY BGCOLOR="#FFFFFF" TOPMARGIN=8>
|
||||
<FONT SIZE=5>
|
||||
<TABLE Border=0><TR VALIGN=MIDDLE><TD>
|
||||
<A ID="Image"> <IMG
|
||||
SRC="file:..\..\..\..\..\win32com\html\image\pycom_blowing.gif"
|
||||
ALT="Clickable Map Image" HEIGHT=113 WIDTH=624 BORDER=0></A>
|
||||
|
||||
</TD></TR>
|
||||
<TR><TD> </TD></TR>
|
||||
<TR VALIGN=MIDDLE><TD VALIGN=MIDDLE ALIGN=CENTER><FONT SIZE=5><INPUT
|
||||
TYPE="text" NAME="TxtLinkDescription" SIZE=50></FONT></TD></TR></TABLE>
|
||||
</FONT>
|
||||
|
||||
<P>
|
||||
A mouse tracking demo. Move the mouse over the image above...
|
||||
|
||||
<SCRIPT Language="Python">
|
||||
<!--
|
||||
# Remember the last location clicked
|
||||
# print("here we go", 1)
|
||||
mx = my = 0
|
||||
|
||||
# class for rectangle testing
|
||||
class rect:
|
||||
def __init__(self, lowx, lowy, upx, upy, desc, url):
|
||||
self.lowx, self.lowy, self.upx, self.upy, self.desc, self.url = \
|
||||
lowx, lowy, upx, upy, desc, url
|
||||
def inside(self, x, y):
|
||||
# print((x,y), "inside", self.desc)
|
||||
result = self.lowx <= x <= self.upx and self.lowy <= y <= self.upy
|
||||
# print(result)
|
||||
return result
|
||||
def mouse_move(self):
|
||||
# print("move", self.desc)
|
||||
ax.TxtLinkDescription.Value = coords + " - " + self.desc
|
||||
def onclick(self):
|
||||
# print("click", self.desc)
|
||||
ax.TxtLinkDescription.Value = coords +" click! " + `self.url`
|
||||
if self.url: ax.location = self.url
|
||||
|
||||
blows = "Blows away "
|
||||
rects =[rect(12,48,59,101,blows+"Visual Basic", ""),
|
||||
rect(107,0,172,58,blows+"Internet Explorer", ""),
|
||||
rect(193,0,261,56,blows+"Microsoft Access", ""),
|
||||
rect(332,43,392,93,blows+"Microsoft Word", ""),
|
||||
rect(457,52,521,99,blows+"Microsoft Excel", ""),
|
||||
rect(537,12,613,85,"Python blows them all away!", "https://www.python.org"),
|
||||
]
|
||||
|
||||
default = rect(0,0,0,0,"Click on an icon","")
|
||||
|
||||
def Image_MouseMove(s, b, x, y):
|
||||
global mx, my, coords
|
||||
coords =`(x,y)`
|
||||
# print(coords)
|
||||
mx, my = x, y
|
||||
for r in rects:
|
||||
if r.inside(x,y):
|
||||
# print(r.desc)
|
||||
r.mouse_move()
|
||||
break
|
||||
else:
|
||||
# print(default.desc)
|
||||
default.mouse_move()
|
||||
|
||||
def Image_OnClick():
|
||||
for r in rects:
|
||||
if r.inside(mx,my):
|
||||
r.onclick()
|
||||
break
|
||||
-->
|
||||
</SCRIPT>
|
||||
|
||||
<P>
|
||||
|
||||
</FONT>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,31 @@
|
||||
#app=WScript.Application
|
||||
#app._print_details_() # Use this to see what Python knows about a COM object.
|
||||
|
||||
g_index = 1
|
||||
# A procedure, using a global.
|
||||
def Show(desc, value = None):
|
||||
global g_index # Need global for g_index, as I locally assign.
|
||||
# No global needed to "xl" object, as only referenced.
|
||||
# Also note "xl" is assigned later in the script - ie, Python is very late bound.
|
||||
xl.Cells(g_index, 1).Value = desc
|
||||
if value: xl.Cells(g_index, 2).Value = value
|
||||
g_index = g_index + 1
|
||||
|
||||
xl = WScript.CreateObject("Excel.Application")
|
||||
import sys
|
||||
|
||||
xl.Visible = 1
|
||||
xl.Workbooks.Add()
|
||||
|
||||
# Show the WScript properties.
|
||||
Show("Application Friendly Name", WScript.Name)
|
||||
Show("Application Version", WScript.Version)
|
||||
Show("Application Context: Fully Qualified Name", WScript.FullName)
|
||||
Show("Application Context: Path Only", WScript.Path)
|
||||
Show("State of Interactive Mode", WScript.Interactive)
|
||||
|
||||
Show("All script arguments:")
|
||||
args = WScript.Arguments
|
||||
|
||||
for i in range(0,args.Count()):
|
||||
Show("Arg %d" % i, args(i))
|
||||
@@ -0,0 +1,44 @@
|
||||
""" Windows Script Host Sample Script
|
||||
' Ported to Python
|
||||
'
|
||||
' ------------------------------------------------------------------------
|
||||
' Copyright (C) 1996 Microsoft Corporation
|
||||
'
|
||||
' You have a royalty-free right to use, modify, reproduce and distribute
|
||||
' the Sample Application Files (and/or any modified version) in any way
|
||||
' you find useful, provided that you agree that Microsoft has no warranty,
|
||||
' obligations or liability for any Sample Application Files.
|
||||
' ------------------------------------------------------------------------
|
||||
'
|
||||
' This sample demonstrates how to write/delete from the registry.
|
||||
"""
|
||||
|
||||
WshShell = WScript.CreateObject("WScript.Shell")
|
||||
|
||||
WshShell.Popup("This script shows how to use registry related methods.", 2)
|
||||
|
||||
WshShell.Popup("Create key HKCU\\Foo with value 'Top level key'")
|
||||
WshShell.RegWrite("HKCU\\Foo\\", "Top level key")
|
||||
|
||||
WshShell.Popup("Create key HKCU\\Foo\\Bar with value 'Second level key'")
|
||||
WshShell.RegWrite( "HKCU\\Foo\\Bar\\", "Second level key")
|
||||
|
||||
WshShell.Popup ("Set value HKCU\\Foo\\Value to REG_SZ 1")
|
||||
WshShell.RegWrite( "HKCU\\Foo\\Value", 1)
|
||||
|
||||
WshShell.Popup ("Set value HKCU\\Foo\\Bar to REG_DWORD 2")
|
||||
WshShell.RegWrite ("HKCU\\Foo\\Bar", 2, "REG_DWORD")
|
||||
|
||||
WshShell.Popup ("Set value HKCU\\Foo\\Bar to REG_EXPAND_SZ '3'")
|
||||
WshShell.RegWrite ("HKCU\\Foo\\Bar\\Baz", "%SystemRoot%\\Foo")
|
||||
|
||||
WshShell.Popup ("Delete value HKCU\\Foo\\Bar\\Baz")
|
||||
WshShell.RegDelete ("HKCU\\Foo\\Bar\\Baz")
|
||||
|
||||
WshShell.Popup ("Delete key HKCU\\Foo\\Bar")
|
||||
WshShell.RegDelete ("HKCU\\Foo\\Bar\\")
|
||||
|
||||
WshShell.Popup ("Delete key HKCU\\Foo")
|
||||
WshShell.RegDelete ("HKCU\\Foo\\")
|
||||
|
||||
WScript.Echo ("Done")
|
||||
@@ -0,0 +1,14 @@
|
||||
# Testall - test core AX support.
|
||||
|
||||
# Test "Restricted Execution" (ie, IObjectSafety).
|
||||
# This will fail if in a "restricted execution" environment, but
|
||||
# will silenty do nothing of not restricted. This same line in an MSIE
|
||||
# script would cause an exception.
|
||||
print("Importing win32api...")
|
||||
import win32api
|
||||
if 1==1:
|
||||
print("Hi")
|
||||
|
||||
WScript.Echo("Hello from WScript")
|
||||
|
||||
#fail
|
||||
@@ -0,0 +1,4 @@
|
||||
# See if we have a special directory for the binaries (for developers)
|
||||
import win32com
|
||||
|
||||
win32com.__PackageSupportBuildPath__(__path__)
|
||||
@@ -0,0 +1,13 @@
|
||||
"""A utility module for ASP (Active Server Pages on MS Internet Info Server.
|
||||
|
||||
Contains:
|
||||
iif -- A utility function to avoid using "if" statements in ASP <% tags
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def iif(cond, t, f):
|
||||
if cond:
|
||||
return t
|
||||
else:
|
||||
return f
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
# This is a Python package
|
||||
@@ -0,0 +1,223 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pythoncom
|
||||
import win32api
|
||||
import winerror
|
||||
from win32com.axdebug import adb, axdebug, documents, gateways
|
||||
from win32com.axdebug.codecontainer import SourceCodeContainer
|
||||
from win32com.axdebug.util import _wrap
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
debuggingTrace = "DEBUG_AXDEBUG" in os.environ # Should we print "trace" output?
|
||||
|
||||
|
||||
def trace(*args):
|
||||
"""A function used instead of "print" for debugging output."""
|
||||
if not debuggingTrace:
|
||||
return
|
||||
print(win32api.GetCurrentThreadId(), end=" ")
|
||||
for arg in args:
|
||||
print(arg, end=" ")
|
||||
print()
|
||||
|
||||
|
||||
# Note that the DebugManager is not a COM gateway class for the
|
||||
# debugger - but it does create and manage them.
|
||||
class DebugManager:
|
||||
_debugger_interfaces_ = [axdebug.IID_IActiveScriptDebug]
|
||||
|
||||
def __init__(self, scriptEngine):
|
||||
self.scriptEngine = scriptEngine
|
||||
self.adb = adb.Debugger()
|
||||
self.rootNode = None
|
||||
self.debugApplication = None
|
||||
self.ccProvider = documents.CodeContainerProvider()
|
||||
try:
|
||||
self.scriptSiteDebug = scriptEngine.GetScriptSite(
|
||||
axdebug.IID_IActiveScriptSiteDebug
|
||||
)
|
||||
except pythoncom.com_error:
|
||||
# No debugger interface (ie, dumb host). Do the extra work.
|
||||
trace("Scripting site has no debugger interface")
|
||||
self.scriptSiteDebug = None
|
||||
# Get the debug application object.
|
||||
self.debugApplication = None
|
||||
if self.scriptSiteDebug is not None:
|
||||
# Spec says that we should test for this, and if it fails revert to
|
||||
# PDM application.
|
||||
try:
|
||||
self.debugApplication = self.scriptSiteDebug.GetApplication()
|
||||
self.rootNode = self.scriptSiteDebug.GetRootApplicationNode()
|
||||
except pythoncom.com_error:
|
||||
self.debugApplication = None
|
||||
|
||||
if self.debugApplication is None:
|
||||
# Try to get/create the default one
|
||||
# NOTE - Don't catch exceptions here - let the parent do it,
|
||||
# so it knows debug support is available.
|
||||
pdm = pythoncom.CoCreateInstance(
|
||||
axdebug.CLSID_ProcessDebugManager,
|
||||
None,
|
||||
pythoncom.CLSCTX_ALL,
|
||||
axdebug.IID_IProcessDebugManager,
|
||||
)
|
||||
self.debugApplication = pdm.GetDefaultApplication()
|
||||
self.rootNode = self.debugApplication.GetRootNode()
|
||||
|
||||
assert (
|
||||
self.debugApplication is not None
|
||||
), "Need to have a DebugApplication object by now!"
|
||||
self.activeScriptDebug = None
|
||||
|
||||
if self.debugApplication is not None:
|
||||
self.adb.AttachApp(self.debugApplication, self.ccProvider)
|
||||
self.codeContainers = {}
|
||||
self.activeScriptDebug = _wrap(
|
||||
ActiveScriptDebug(self, self.codeContainers), axdebug.IID_IActiveScriptDebug
|
||||
)
|
||||
|
||||
def Close(self):
|
||||
# Called by the language engine when it receives a close request
|
||||
self.activeScriptDebug = None
|
||||
self.scriptEngine = None
|
||||
self.rootNode = None
|
||||
self.debugApplication = None
|
||||
self.scriptSiteDebug = None
|
||||
if self.ccProvider is not None:
|
||||
self.ccProvider.Close()
|
||||
self.ccProvider = None
|
||||
self.codeContainers = {}
|
||||
if self.adb:
|
||||
self.adb.CloseApp()
|
||||
self.adb = None
|
||||
|
||||
# print("Close complete")
|
||||
|
||||
def IsAnyHost(self):
|
||||
"Do we have _any_ debugging interfaces installed?"
|
||||
return self.debugApplication is not None
|
||||
|
||||
def IsSimpleHost(self):
|
||||
return self.scriptSiteDebug is None
|
||||
|
||||
def HandleRuntimeError(self):
|
||||
"""Called by the engine when a runtime error occurs. If we have a debugger,
|
||||
we let it know.
|
||||
|
||||
The result is a boolean which indicates if the error handler should call
|
||||
IActiveScriptSite::OnScriptError()
|
||||
"""
|
||||
# if self.IsAnyHost:
|
||||
# site = _wrap(self, axdebug.IID_IActiveScriptSite)
|
||||
# breakResume, errorResume, fCallOnError = self.debugApplication(activeScriptErrorDebug, site)
|
||||
# Do something with these!
|
||||
# else:
|
||||
trace("HandleRuntimeError")
|
||||
fCallOnError = 1
|
||||
return fCallOnError
|
||||
|
||||
def _query_interface_for_debugger_(self, iid):
|
||||
if iid in self._debugger_interfaces_:
|
||||
return self.activeScriptDebug
|
||||
trace("DebugManager QI - unknown IID", iid)
|
||||
return 0
|
||||
|
||||
def OnEnterScript(self):
|
||||
trace("OnEnterScript")
|
||||
self.adb.SetupAXDebugging(sys._getframe().f_back)
|
||||
|
||||
def OnLeaveScript(self):
|
||||
trace("OnLeaveScript")
|
||||
self.adb.ResetAXDebugging()
|
||||
|
||||
def AddScriptBlock(self, codeBlock):
|
||||
# If we don't have debugging support, don't bother.
|
||||
cc = DebugCodeBlockContainer(codeBlock, self.scriptSiteDebug)
|
||||
if self.IsSimpleHost():
|
||||
document = documents.DebugDocumentText(cc)
|
||||
document = _wrap(document, axdebug.IID_IDebugDocument)
|
||||
provider = documents.DebugDocumentProvider(document)
|
||||
provider = _wrap(provider, axdebug.IID_IDebugDocumentProvider)
|
||||
cc.debugDocument = document
|
||||
newNode = self.debugApplication.CreateApplicationNode()
|
||||
newNode.SetDocumentProvider(provider)
|
||||
newNode.Attach(self.rootNode)
|
||||
else:
|
||||
newNode = None # Managed by smart host.
|
||||
self.codeContainers[cc.sourceContext] = cc
|
||||
self.ccProvider.AddCodeContainer(cc, newNode)
|
||||
|
||||
|
||||
class DebugCodeBlockContainer(SourceCodeContainer):
|
||||
def __init__(self, codeBlock, site):
|
||||
self.codeBlock = codeBlock
|
||||
SourceCodeContainer.__init__(
|
||||
self,
|
||||
codeBlock.codeText,
|
||||
codeBlock.GetFileName(),
|
||||
codeBlock.sourceContextCookie,
|
||||
codeBlock.startLineNumber,
|
||||
site,
|
||||
)
|
||||
|
||||
def GetName(self, dnt):
|
||||
if dnt == axdebug.DOCUMENTNAMETYPE_APPNODE:
|
||||
return self.codeBlock.GetDisplayName()
|
||||
elif dnt == axdebug.DOCUMENTNAMETYPE_TITLE:
|
||||
return self.codeBlock.GetDisplayName()
|
||||
# elif dnt==axdebug.DOCUMENTNAMETYPE_FILE_TAIL:
|
||||
# elif dnt==axdebug.DOCUMENTNAMETYPE_URL:
|
||||
else:
|
||||
raise COMException(scode=winerror.S_FALSE)
|
||||
|
||||
|
||||
class EnumDebugCodeContexts(gateways.EnumDebugCodeContexts):
|
||||
def _wrap(self, ob):
|
||||
return ob
|
||||
|
||||
|
||||
class ActiveScriptDebug:
|
||||
"""The class which implements the IActiveScriptDebug interface for the Active Script engine.
|
||||
|
||||
Only ever used by smart hosts.
|
||||
"""
|
||||
|
||||
_public_methods_ = [
|
||||
"GetScriptTextAttributes",
|
||||
"GetScriptletTextAttributes",
|
||||
"EnumCodeContextsOfPosition",
|
||||
]
|
||||
_com_interfaces_ = [axdebug.IID_IActiveScriptDebug]
|
||||
|
||||
def __init__(self, debugMgr, codeContainers):
|
||||
self.debugMgr = debugMgr
|
||||
self.scriptSiteDebug = debugMgr.scriptSiteDebug
|
||||
self.codeContainers = codeContainers
|
||||
|
||||
def _Close(self):
|
||||
self.debugMgr = None
|
||||
self.scriptSiteDebug = None
|
||||
self.codeContainers = {}
|
||||
|
||||
def _query_interface_(self, iid):
|
||||
trace("DebuggerQI with", iid)
|
||||
return _wrap(self.debugMgr.scriptEngine, iid)
|
||||
|
||||
def GetScriptTextAttributes(self, code, delim, flags):
|
||||
container = SourceCodeContainer(code, "<Temp Code Block>")
|
||||
return container.GetSyntaxColorAttributes()
|
||||
|
||||
def GetScriptletTextAttributes(self, code, delim, flags):
|
||||
trace("GetScriptletTextAttributes", code, delim, flags)
|
||||
container = SourceCodeContainer(code, "<Temp Code Block>")
|
||||
return container.GetSyntaxColorAttributes()
|
||||
|
||||
def EnumCodeContextsOfPosition(self, context, charOffset, numChars):
|
||||
trace("EnumCodeContextsOfPosition", context, charOffset, numChars)
|
||||
try:
|
||||
context = self.codeContainers[context].GetCodeContextAtPosition(charOffset)
|
||||
except KeyError:
|
||||
raise COMException(scode=winerror.E_UNEXPECTED)
|
||||
enum = EnumDebugCodeContexts([context])
|
||||
return _wrap(enum, axdebug.IID_IEnumDebugCodeContexts)
|
||||
@@ -0,0 +1,262 @@
|
||||
"""Exception and error handling.
|
||||
|
||||
This contains the core exceptions that the implementations should raise
|
||||
as well as the IActiveScriptError interface code.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import traceback
|
||||
import warnings
|
||||
from types import TracebackType
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import pythoncom
|
||||
import win32com.server.util
|
||||
import winerror
|
||||
from win32com.axscript import axscript
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from win32comext.axscript.client.debug import DebugManager
|
||||
from win32comext.axscript.client.framework import AXScriptCodeBlock, COMScript
|
||||
from win32comext.axscript.server.axsite import AXSite
|
||||
|
||||
debugging = 0
|
||||
|
||||
|
||||
def FormatForAX(text: str):
|
||||
"""Format a string suitable for an AX Host"""
|
||||
# Replace all " with ', so it works OK in HTML (ie, ASP)
|
||||
return ExpandTabs(AddCR(text))
|
||||
|
||||
|
||||
def ExpandTabs(text: str):
|
||||
return re.sub(r"\t", " ", text)
|
||||
|
||||
|
||||
def AddCR(text: str):
|
||||
return re.sub(r"\n", "\r\n", text)
|
||||
|
||||
|
||||
class IActiveScriptError:
|
||||
"""An implementation of IActiveScriptError
|
||||
|
||||
The ActiveX Scripting host calls this client whenever we report
|
||||
an exception to it. This interface provides the exception details
|
||||
for the host to report to the user.
|
||||
"""
|
||||
|
||||
_com_interfaces_ = [axscript.IID_IActiveScriptError]
|
||||
_public_methods_ = ["GetSourceLineText", "GetSourcePosition", "GetExceptionInfo"]
|
||||
|
||||
def _query_interface_(self, iid):
|
||||
print("IActiveScriptError QI - unknown IID", iid)
|
||||
return 0
|
||||
|
||||
def _SetExceptionInfo(self, exc: AXScriptException):
|
||||
self.exception = exc
|
||||
|
||||
def GetSourceLineText(self):
|
||||
return self.exception.linetext
|
||||
|
||||
def GetSourcePosition(self):
|
||||
ctx = self.exception.sourceContext
|
||||
# Zero based in the debugger (but our columns are too!)
|
||||
return (
|
||||
ctx,
|
||||
self.exception.lineno + self.exception.startLineNo - 1,
|
||||
self.exception.colno,
|
||||
)
|
||||
|
||||
def GetExceptionInfo(self):
|
||||
return self.exception
|
||||
|
||||
|
||||
class AXScriptException(COMException):
|
||||
"""A class used as a COM exception.
|
||||
|
||||
Note this has attributes which conform to the standard attributes
|
||||
for COM exceptions, plus a few others specific to our IActiveScriptError
|
||||
object.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
site: COMScript,
|
||||
codeBlock: AXScriptCodeBlock | None,
|
||||
exc_type: None = None,
|
||||
exc_value: BaseException | None = None,
|
||||
exc_traceback: None = None,
|
||||
):
|
||||
# set properties base class shares via base ctor...
|
||||
super().__init__(
|
||||
description="Unknown Exception",
|
||||
scode=winerror.DISP_E_EXCEPTION,
|
||||
source="Python ActiveX Scripting Engine",
|
||||
)
|
||||
|
||||
if exc_type is not None or exc_traceback is not None:
|
||||
warnings.warn(
|
||||
"`exc_type` and `exc_traceback` were redundant and are now unused.",
|
||||
category=DeprecationWarning,
|
||||
)
|
||||
|
||||
# And my other values...
|
||||
if codeBlock is None:
|
||||
self.sourceContext = 0
|
||||
self.startLineNo = 0
|
||||
else:
|
||||
self.sourceContext = codeBlock.sourceContextCookie
|
||||
self.startLineNo = codeBlock.startLineNumber
|
||||
self.linetext = ""
|
||||
|
||||
self.__BuildFromException(site, exc_value)
|
||||
|
||||
def __BuildFromException(self, site: COMScript, value: BaseException | None):
|
||||
if debugging:
|
||||
import linecache
|
||||
|
||||
linecache.clearcache()
|
||||
try:
|
||||
if isinstance(value, SyntaxError):
|
||||
self._BuildFromSyntaxError(value)
|
||||
else:
|
||||
self._BuildFromOther(site, value)
|
||||
except: # Error extracting traceback info!!!
|
||||
traceback.print_exc()
|
||||
# re-raise.
|
||||
raise
|
||||
|
||||
def _BuildFromSyntaxError(self, exc: SyntaxError):
|
||||
# Some of these may be None, which upsets us!
|
||||
msg = exc.msg or "Unknown Error"
|
||||
offset = exc.offset or 0
|
||||
line = exc.text or ""
|
||||
lineno = exc.lineno or 0
|
||||
|
||||
self.description = FormatForAX(msg)
|
||||
self.lineno = lineno
|
||||
self.colno = offset - 1
|
||||
self.linetext = ExpandTabs(line.rstrip())
|
||||
|
||||
def _BuildFromOther(self, site: COMScript, value: BaseException | None):
|
||||
tb = value.__traceback__ if value else None
|
||||
exc_type = type(value) if value else None
|
||||
self.colno = -1
|
||||
self.lineno = 0
|
||||
if debugging: # Full traceback if debugging.
|
||||
list = traceback.format_exception(exc_type, value, tb)
|
||||
self.description = ExpandTabs("".join(list))
|
||||
return
|
||||
# Run down the traceback list, looking for the first "<Script..>"
|
||||
# Hide traceback above this. In addition, keep going down
|
||||
# looking for a "_*_" attribute, and below hide these also.
|
||||
hide_names = [
|
||||
"r_import",
|
||||
"r_reload",
|
||||
"r_open",
|
||||
] # hide from these functions down in the traceback.
|
||||
tb_top = tb
|
||||
while tb_top:
|
||||
filename, lineno, name, line = self.ExtractTracebackInfo(tb_top, site)
|
||||
if filename[:7] == "<Script":
|
||||
break
|
||||
tb_top = tb_top.tb_next
|
||||
format_items = []
|
||||
if tb_top: # found one.
|
||||
tb_look: TracebackType | None = tb_top
|
||||
# Look down for our bottom
|
||||
while tb_look:
|
||||
filename, lineno, name, line = self.ExtractTracebackInfo(tb_look, site)
|
||||
if name in hide_names:
|
||||
break
|
||||
# We can report a line-number, but not a filename. Therefore,
|
||||
# we return the last line-number we find in one of our script
|
||||
# blocks.
|
||||
if filename.startswith("<Script"):
|
||||
self.lineno = lineno
|
||||
self.linetext = line
|
||||
format_items.append((filename, lineno, name, line))
|
||||
tb_look = tb_look.tb_next
|
||||
else:
|
||||
tb_top = tb
|
||||
|
||||
bits = ["Traceback (most recent call last):\n"]
|
||||
bits.extend(traceback.format_list(format_items))
|
||||
if isinstance(value, pythoncom.com_error):
|
||||
desc = f"{value.strerror} (0x{value.hresult:x})"
|
||||
if (
|
||||
value.hresult == winerror.DISP_E_EXCEPTION
|
||||
and value.excepinfo
|
||||
and value.excepinfo[2]
|
||||
):
|
||||
desc = value.excepinfo[2]
|
||||
bits.append("COM Error: " + desc)
|
||||
else:
|
||||
bits.extend(traceback.format_exception_only(exc_type, value))
|
||||
|
||||
self.description = ExpandTabs("".join(bits))
|
||||
|
||||
def ExtractTracebackInfo(self, tb: TracebackType, site: COMScript):
|
||||
import linecache
|
||||
|
||||
lineno = tb.tb_lineno
|
||||
co = tb.tb_frame.f_code
|
||||
filename = co.co_filename
|
||||
name = co.co_name
|
||||
line: str | None = linecache.getline(filename, lineno)
|
||||
if not line:
|
||||
codeBlock = site.scriptCodeBlocks.get(filename)
|
||||
if codeBlock:
|
||||
# Note: 'line' will now be unicode.
|
||||
line = codeBlock.GetLineNo(lineno)
|
||||
if line:
|
||||
line = line.strip()
|
||||
else:
|
||||
line = None
|
||||
return filename, lineno, name, line
|
||||
|
||||
def __repr__(self):
|
||||
return "AXScriptException Object with description:" + self.description
|
||||
|
||||
|
||||
def ProcessAXScriptException(
|
||||
scriptingSite: AXSite,
|
||||
debugManager: DebugManager,
|
||||
exceptionInstance: AXScriptException,
|
||||
):
|
||||
"""General function to handle any exception in AX code
|
||||
|
||||
This function creates an instance of our IActiveScriptError interface, and
|
||||
gives it to the host, along with out exception class. The host will
|
||||
likely call back on the IActiveScriptError interface to get the source text
|
||||
and other information not normally in COM exceptions.
|
||||
"""
|
||||
# traceback.print_exc()
|
||||
instance = IActiveScriptError()
|
||||
instance._SetExceptionInfo(exceptionInstance)
|
||||
gateway = win32com.server.util.wrap(instance, axscript.IID_IActiveScriptError)
|
||||
if debugManager:
|
||||
fCallOnError = debugManager.HandleRuntimeError()
|
||||
if not fCallOnError:
|
||||
return None
|
||||
|
||||
try:
|
||||
result = scriptingSite.OnScriptError(gateway)
|
||||
except pythoncom.com_error as details:
|
||||
print("**OnScriptError failed:", details)
|
||||
print(f"Exception description: '{exceptionInstance.description!r}'")
|
||||
print(f"Exception text: '{exceptionInstance.linetext!r}'")
|
||||
result = winerror.S_FALSE
|
||||
|
||||
if result == winerror.S_OK:
|
||||
# If the above returns NOERROR, it is assumed the error has been
|
||||
# correctly registered and the value SCRIPT_E_REPORTED is returned.
|
||||
ret = COMException(scode=axscript.SCRIPT_E_REPORTED)
|
||||
return ret
|
||||
else:
|
||||
# The error is taken to be unreported and is propagated up the call stack
|
||||
# via the IDispatch::Invoke's EXCEPINFO parameter (hr returned is DISP_E_EXCEPTION.
|
||||
return exceptionInstance
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,78 @@
|
||||
# pydumper.py
|
||||
#
|
||||
# This is being worked on - it does not yet work at all, in ay way
|
||||
# shape or form :-)
|
||||
#
|
||||
# A new script engine, derived from the standard scripting engine,
|
||||
# which dumps information.
|
||||
|
||||
# This generally can be used to grab all sorts of useful details about
|
||||
# an engine - expose bugs in it or Python, dump the object model, etc.
|
||||
|
||||
# As it is derived from the standard engine, it fully supports Python
|
||||
# as a scripting language - meaning the dumps produced can be quite dynamic,
|
||||
# and based on the script code you execute.
|
||||
|
||||
import sys
|
||||
|
||||
import win32api
|
||||
import win32con
|
||||
from win32com.axscript import axscript
|
||||
|
||||
from . import pyscript
|
||||
|
||||
PyDump_CLSID = "{ac527e60-c693-11d0-9c25-00aa00125a98}"
|
||||
|
||||
|
||||
class AXScriptAttribute(pyscript.AXScriptAttribute):
|
||||
pass
|
||||
|
||||
|
||||
class NamedScriptAttribute(pyscript.NamedScriptAttribute):
|
||||
pass
|
||||
|
||||
|
||||
class PyScript(pyscript.PyScript):
|
||||
pass
|
||||
|
||||
|
||||
def Register():
|
||||
if "-d" in sys.argv:
|
||||
dispatcher = "DispatcherWin32trace"
|
||||
debug_desc = " (" + dispatcher + ")"
|
||||
debug_option = "Yes"
|
||||
else:
|
||||
dispatcher = None
|
||||
debug_desc = ""
|
||||
debug_option = ""
|
||||
|
||||
categories = [axscript.CATID_ActiveScript, axscript.CATID_ActiveScriptParse]
|
||||
clsid = PyDump_CLSID
|
||||
lcid = 0x0409 # // english
|
||||
policy = None # "win32com.axscript.client.axspolicy.AXScriptPolicy"
|
||||
|
||||
print("Registering COM server%s..." % debug_desc)
|
||||
from win32com.server.register import RegisterServer, _set_string
|
||||
|
||||
languageName = "PyDump"
|
||||
verProgId = "Python.Dumper.1"
|
||||
RegisterServer(
|
||||
clsid=clsid,
|
||||
pythonInstString="win32com.axscript.client.pyscript.PyDumper",
|
||||
desc="Python Debugging/Dumping ActiveX Scripting Engine",
|
||||
progID=languageName,
|
||||
verProgID=verProgId,
|
||||
policy=policy,
|
||||
catids=categories,
|
||||
dispatcher=dispatcher,
|
||||
)
|
||||
|
||||
win32api.RegCreateKey(win32con.HKEY_CLASSES_ROOT, languageName + "\\OLEScript")
|
||||
# Basic Registration for wsh.
|
||||
_set_string(".pysDump", "pysDumpFile")
|
||||
_set_string("pysDumpFile\\ScriptEngine", languageName)
|
||||
print("Dumping Server registered.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
Register()
|
||||
@@ -0,0 +1,438 @@
|
||||
"""Python ActiveX Scripting Implementation
|
||||
|
||||
This module implements the Python ActiveX Scripting client.
|
||||
|
||||
To register the implementation, simply "run" this Python program - ie
|
||||
either double-click on it, or run "python.exe pyscript.py" from the
|
||||
command line.
|
||||
"""
|
||||
|
||||
import re
|
||||
import types
|
||||
|
||||
import pythoncom
|
||||
import win32com
|
||||
import win32com.client.dynamic
|
||||
import win32com.server.register
|
||||
import winerror
|
||||
from win32com.axscript import axscript
|
||||
from win32com.axscript.client import framework, scriptdispatch
|
||||
from win32com.axscript.client.framework import (
|
||||
SCRIPTTEXT_FORCEEXECUTION,
|
||||
SCRIPTTEXT_ISEXPRESSION,
|
||||
SCRIPTTEXT_ISPERSISTENT,
|
||||
trace,
|
||||
)
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
PyScript_CLSID = "{DF630910-1C1D-11d0-AE36-8C0F5E000000}"
|
||||
|
||||
debugging_attr = 0
|
||||
|
||||
|
||||
def debug_attr_print(*args):
|
||||
if debugging_attr:
|
||||
trace(*args)
|
||||
|
||||
|
||||
def ExpandTabs(text):
|
||||
return re.sub(r"\t", " ", text)
|
||||
|
||||
|
||||
def AddCR(text):
|
||||
return re.sub(r"\n", "\r\n", text)
|
||||
|
||||
|
||||
class AXScriptCodeBlock(framework.AXScriptCodeBlock):
|
||||
def GetDisplayName(self):
|
||||
return "PyScript - " + framework.AXScriptCodeBlock.GetDisplayName(self)
|
||||
|
||||
|
||||
# There is only ever _one_ ax object - it exists in the global namespace
|
||||
# for all script items.
|
||||
# It performs a search from all global/visible objects
|
||||
# down.
|
||||
# This means that if 2 sub-objects of the same name are used
|
||||
# then only one is ever reachable using the ax shortcut.
|
||||
class AXScriptAttribute:
|
||||
"An attribute in a scripts namespace."
|
||||
|
||||
def __init__(self, engine):
|
||||
self.__dict__["_scriptEngine_"] = engine
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr[1] == "_" and attr[:-1] == "_":
|
||||
raise AttributeError(attr)
|
||||
rc = self._FindAttribute_(attr)
|
||||
if rc is None:
|
||||
raise AttributeError(attr)
|
||||
return rc
|
||||
|
||||
def _Close_(self):
|
||||
self.__dict__["_scriptEngine_"] = None
|
||||
|
||||
def _DoFindAttribute_(self, obj, attr):
|
||||
try:
|
||||
return obj.subItems[attr.lower()].attributeObject
|
||||
except KeyError:
|
||||
pass
|
||||
# Check out the sub-items
|
||||
for item in obj.subItems.values():
|
||||
try:
|
||||
return self._DoFindAttribute_(item, attr)
|
||||
except AttributeError:
|
||||
pass
|
||||
raise AttributeError(attr)
|
||||
|
||||
def _FindAttribute_(self, attr):
|
||||
for item in self._scriptEngine_.subItems.values():
|
||||
try:
|
||||
return self._DoFindAttribute_(item, attr)
|
||||
except AttributeError:
|
||||
pass
|
||||
# All else fails, see if it is a global
|
||||
# (mainly b/w compat)
|
||||
return getattr(self._scriptEngine_.globalNameSpaceModule, attr)
|
||||
|
||||
|
||||
# raise AttributeError(attr)
|
||||
|
||||
|
||||
class NamedScriptAttribute:
|
||||
"An explicitly named object in an objects namespace"
|
||||
|
||||
# Each named object holds a reference to one of these.
|
||||
# Whenever a sub-item appears in a namespace, it is really one of these
|
||||
# objects. Has a circular reference back to the item itself, which is
|
||||
# closed via _Close_()
|
||||
def __init__(self, scriptItem):
|
||||
self.__dict__["_scriptItem_"] = scriptItem
|
||||
|
||||
def __repr__(self):
|
||||
return f"<NamedItemAttribute{self._scriptItem_!r}>"
|
||||
|
||||
def __getattr__(self, attr):
|
||||
# If a known subitem, return it.
|
||||
try:
|
||||
return self._scriptItem_.subItems[attr.lower()].attributeObject
|
||||
except KeyError:
|
||||
# Otherwise see if the dispatch can give it to us
|
||||
if self._scriptItem_.dispatchContainer:
|
||||
return getattr(self._scriptItem_.dispatchContainer, attr)
|
||||
raise AttributeError(attr)
|
||||
|
||||
def __setattr__(self, attr, value):
|
||||
# XXX - todo - if a known item, then should call its default
|
||||
# dispatch method.
|
||||
attr = attr.lower()
|
||||
if self._scriptItem_.dispatchContainer:
|
||||
try:
|
||||
return setattr(self._scriptItem_.dispatchContainer, attr, value)
|
||||
except AttributeError:
|
||||
pass
|
||||
raise AttributeError(attr)
|
||||
|
||||
def _Close_(self):
|
||||
self.__dict__["_scriptItem_"] = None
|
||||
|
||||
|
||||
class ScriptItem(framework.ScriptItem):
|
||||
def __init__(self, parentItem, name, dispatch, flags):
|
||||
framework.ScriptItem.__init__(self, parentItem, name, dispatch, flags)
|
||||
self.scriptlets = {}
|
||||
self.attributeObject = None
|
||||
|
||||
def Reset(self):
|
||||
framework.ScriptItem.Reset(self)
|
||||
if self.attributeObject:
|
||||
self.attributeObject._Close_()
|
||||
self.attributeObject = None
|
||||
|
||||
def Close(self):
|
||||
framework.ScriptItem.Close(self) # calls reset.
|
||||
self.dispatchContainer = None
|
||||
self.scriptlets = {}
|
||||
|
||||
def Register(self):
|
||||
framework.ScriptItem.Register(self)
|
||||
self.attributeObject = NamedScriptAttribute(self)
|
||||
if self.dispatch:
|
||||
# Need to avoid the new Python "lazy" dispatch behaviour.
|
||||
olerepr, clsid = None
|
||||
try:
|
||||
engine = self.GetEngine()
|
||||
typeinfo = self.dispatch.GetTypeInfo()
|
||||
clsid = typeinfo.GetTypeAttr()[0]
|
||||
olerepr = engine.mapKnownCOMTypes.get(clsid)
|
||||
except pythoncom.com_error:
|
||||
typeinfo = None
|
||||
if olerepr is None:
|
||||
olerepr = win32com.client.dynamic.MakeOleRepr(
|
||||
self.dispatch, typeinfo, None
|
||||
)
|
||||
if clsid is not None:
|
||||
engine.mapKnownCOMTypes[clsid] = olerepr
|
||||
self.dispatchContainer = win32com.client.dynamic.CDispatch(
|
||||
self.dispatch, olerepr, self.name
|
||||
)
|
||||
|
||||
|
||||
# self.dispatchContainer = win32com.client.dynamic.Dispatch(self.dispatch, userName = self.name)
|
||||
# self.dispatchContainer = win32com.client.dynamic.DumbDispatch(self.dispatch, userName = self.name)
|
||||
|
||||
# def Connect(self):
|
||||
# framework.ScriptItem.Connect(self)
|
||||
# def Disconnect(self):
|
||||
# framework.ScriptItem.Disconnect(self)
|
||||
|
||||
|
||||
class PyScript(framework.COMScript):
|
||||
# Setup the auto-registration stuff...
|
||||
_reg_verprogid_ = "Python.AXScript.2"
|
||||
_reg_progid_ = "Python"
|
||||
# _reg_policy_spec_ = default
|
||||
_reg_catids_ = [axscript.CATID_ActiveScript, axscript.CATID_ActiveScriptParse]
|
||||
_reg_desc_ = "Python ActiveX Scripting Engine"
|
||||
_reg_clsid_ = PyScript_CLSID
|
||||
_reg_class_spec_ = "win32com.axscript.client.pyscript.PyScript"
|
||||
_reg_remove_keys_ = [(".pys",), ("pysFile",)]
|
||||
_reg_threading_ = "both"
|
||||
|
||||
def __init__(self):
|
||||
framework.COMScript.__init__(self)
|
||||
self.globalNameSpaceModule = None
|
||||
self.codeBlocks = []
|
||||
self.scriptDispatch = None
|
||||
|
||||
def InitNew(self):
|
||||
framework.COMScript.InitNew(self)
|
||||
|
||||
self.scriptDispatch = None
|
||||
self.globalNameSpaceModule = types.ModuleType("__ax_main__")
|
||||
self.globalNameSpaceModule.__dict__["ax"] = AXScriptAttribute(self)
|
||||
|
||||
self.codeBlocks = []
|
||||
self.persistedCodeBlocks = []
|
||||
self.mapKnownCOMTypes = {} # Map of known CLSID to typereprs
|
||||
self.codeBlockCounter = 0
|
||||
|
||||
def Stop(self):
|
||||
# Flag every pending script as already done
|
||||
for b in self.codeBlocks:
|
||||
b.beenExecuted = 1
|
||||
return framework.COMScript.Stop(self)
|
||||
|
||||
def Reset(self):
|
||||
# Reset all code-blocks that are persistent, and discard the rest
|
||||
oldCodeBlocks = self.codeBlocks[:]
|
||||
self.codeBlocks = []
|
||||
for b in oldCodeBlocks:
|
||||
if b.flags & SCRIPTTEXT_ISPERSISTENT:
|
||||
b.beenExecuted = 0
|
||||
self.codeBlocks.append(b)
|
||||
return framework.COMScript.Reset(self)
|
||||
|
||||
def _GetNextCodeBlockNumber(self):
|
||||
self.codeBlockCounter += 1
|
||||
return self.codeBlockCounter
|
||||
|
||||
def RegisterNamedItem(self, item):
|
||||
wasReg = item.isRegistered
|
||||
framework.COMScript.RegisterNamedItem(self, item)
|
||||
if not wasReg:
|
||||
# Insert into our namespace.
|
||||
# Add every item by name
|
||||
if item.IsVisible():
|
||||
self.globalNameSpaceModule.__dict__[item.name] = item.attributeObject
|
||||
if item.IsGlobal():
|
||||
# Global items means sub-items are also added...
|
||||
for subitem in item.subItems.values():
|
||||
self.globalNameSpaceModule.__dict__[subitem.name] = (
|
||||
subitem.attributeObject
|
||||
)
|
||||
# Also add all methods
|
||||
for name, entry in item.dispatchContainer._olerepr_.mapFuncs.items():
|
||||
if not entry.hidden:
|
||||
self.globalNameSpaceModule.__dict__[name] = getattr(
|
||||
item.dispatchContainer, name
|
||||
)
|
||||
|
||||
def DoExecutePendingScripts(self):
|
||||
try:
|
||||
globs = self.globalNameSpaceModule.__dict__
|
||||
for codeBlock in self.codeBlocks:
|
||||
if not codeBlock.beenExecuted:
|
||||
if self.CompileInScriptedSection(codeBlock, "exec"):
|
||||
self.ExecInScriptedSection(codeBlock, globs)
|
||||
finally:
|
||||
pass
|
||||
|
||||
def DoRun(self):
|
||||
pass
|
||||
|
||||
def Close(self):
|
||||
self.ResetNamespace()
|
||||
self.globalNameSpaceModule = None
|
||||
self.codeBlocks = []
|
||||
self.scriptDispatch = None
|
||||
framework.COMScript.Close(self)
|
||||
|
||||
def GetScriptDispatch(self, name):
|
||||
# trace("GetScriptDispatch with", name)
|
||||
# if name is not None: return None
|
||||
if self.scriptDispatch is None:
|
||||
self.scriptDispatch = scriptdispatch.MakeScriptDispatch(
|
||||
self, self.globalNameSpaceModule
|
||||
)
|
||||
return self.scriptDispatch
|
||||
|
||||
def MakeEventMethodName(self, subItemName, eventName):
|
||||
return (
|
||||
subItemName[0].upper()
|
||||
+ subItemName[1:]
|
||||
+ "_"
|
||||
+ eventName[0].upper()
|
||||
+ eventName[1:]
|
||||
)
|
||||
|
||||
def DoAddScriptlet(
|
||||
self,
|
||||
defaultName,
|
||||
code,
|
||||
itemName,
|
||||
subItemName,
|
||||
eventName,
|
||||
delimiter,
|
||||
sourceContextCookie,
|
||||
startLineNumber,
|
||||
):
|
||||
# Just store the code away - compile when called. (JIT :-)
|
||||
item = self.GetNamedItem(itemName)
|
||||
if (
|
||||
itemName == subItemName
|
||||
): # Explicit handlers - eg <SCRIPT LANGUAGE="Python" for="TestForm" Event="onSubmit">
|
||||
subItem = item
|
||||
else:
|
||||
subItem = item.GetCreateSubItem(item, subItemName, None, None)
|
||||
funcName = self.MakeEventMethodName(subItemName, eventName)
|
||||
|
||||
codeBlock = AXScriptCodeBlock(
|
||||
"Script Event %s" % funcName, code, sourceContextCookie, startLineNumber, 0
|
||||
)
|
||||
self._AddScriptCodeBlock(codeBlock)
|
||||
subItem.scriptlets[funcName] = codeBlock
|
||||
|
||||
def DoProcessScriptItemEvent(self, item, event, lcid, wFlags, args):
|
||||
# trace("ScriptItemEvent", self, item, event, event.name, lcid, wFlags, args)
|
||||
funcName = self.MakeEventMethodName(item.name, event.name)
|
||||
codeBlock = function = None
|
||||
try:
|
||||
function = item.scriptlets[funcName]
|
||||
if isinstance(function, PyScript): # ie, is a CodeBlock instance
|
||||
codeBlock = function
|
||||
function = None
|
||||
except KeyError:
|
||||
pass
|
||||
if codeBlock is not None:
|
||||
realCode = "def %s():\n" % funcName
|
||||
for line in framework.RemoveCR(codeBlock.codeText).split("\n"):
|
||||
realCode += "\t" + line + "\n"
|
||||
realCode += "\n"
|
||||
if not self.CompileInScriptedSection(codeBlock, "exec", realCode):
|
||||
return
|
||||
dict = {}
|
||||
self.ExecInScriptedSection(
|
||||
codeBlock, self.globalNameSpaceModule.__dict__, dict
|
||||
)
|
||||
function = dict[funcName]
|
||||
# cache back in scriptlets as a function.
|
||||
item.scriptlets[funcName] = function
|
||||
if function is None:
|
||||
# still no function - see if in the global namespace.
|
||||
try:
|
||||
function = self.globalNameSpaceModule.__dict__[funcName]
|
||||
except KeyError:
|
||||
# Not there _exactly_ - do case ins search.
|
||||
funcNameLook = funcName.lower()
|
||||
for attr in self.globalNameSpaceModule.__dict__:
|
||||
if funcNameLook == attr.lower():
|
||||
function = self.globalNameSpaceModule.__dict__[attr]
|
||||
# cache back in scriptlets, to avoid this overhead next time
|
||||
item.scriptlets[funcName] = function
|
||||
|
||||
if function is None:
|
||||
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
|
||||
return self.ApplyInScriptedSection(codeBlock, function, args)
|
||||
|
||||
def DoParseScriptText(
|
||||
self, code, sourceContextCookie, startLineNumber, bWantResult, flags
|
||||
):
|
||||
code = framework.RemoveCR(code) + "\n"
|
||||
if flags & SCRIPTTEXT_ISEXPRESSION:
|
||||
name = "Script Expression"
|
||||
exec_type = "eval"
|
||||
else:
|
||||
name = "Script Block"
|
||||
exec_type = "exec"
|
||||
num = self._GetNextCodeBlockNumber()
|
||||
if num == 1:
|
||||
num = ""
|
||||
name += f" {num}"
|
||||
codeBlock = AXScriptCodeBlock(
|
||||
name, code, sourceContextCookie, startLineNumber, flags
|
||||
)
|
||||
self._AddScriptCodeBlock(codeBlock)
|
||||
globs = self.globalNameSpaceModule.__dict__
|
||||
if bWantResult: # always immediate.
|
||||
if self.CompileInScriptedSection(codeBlock, exec_type):
|
||||
if flags & SCRIPTTEXT_ISEXPRESSION:
|
||||
return self.EvalInScriptedSection(codeBlock, globs)
|
||||
else:
|
||||
return self.ExecInScriptedSection(codeBlock, globs)
|
||||
|
||||
# else compile failed, but user chose to keep running...
|
||||
else:
|
||||
if flags & SCRIPTTEXT_FORCEEXECUTION:
|
||||
if self.CompileInScriptedSection(codeBlock, exec_type):
|
||||
self.ExecInScriptedSection(codeBlock, globs)
|
||||
else:
|
||||
self.codeBlocks.append(codeBlock)
|
||||
|
||||
def GetNamedItemClass(self):
|
||||
return ScriptItem
|
||||
|
||||
def ResetNamespace(self):
|
||||
if self.globalNameSpaceModule is not None:
|
||||
try:
|
||||
self.globalNameSpaceModule.ax._Reset_()
|
||||
except AttributeError:
|
||||
pass # ???
|
||||
globalNameSpaceModule = None
|
||||
|
||||
|
||||
def DllRegisterServer():
|
||||
klass = PyScript
|
||||
win32com.server.register._set_subkeys(
|
||||
klass._reg_progid_ + "\\OLEScript", {}
|
||||
) # Just a CreateKey
|
||||
# Basic Registration for wsh.
|
||||
win32com.server.register._set_string(".pys", "pysFile")
|
||||
win32com.server.register._set_string("pysFile\\ScriptEngine", klass._reg_progid_)
|
||||
guid_wsh_shellex = "{60254CA5-953B-11CF-8C96-00AA00B8708C}"
|
||||
win32com.server.register._set_string(
|
||||
"pysFile\\ShellEx\\DropHandler", guid_wsh_shellex
|
||||
)
|
||||
win32com.server.register._set_string(
|
||||
"pysFile\\ShellEx\\PropertySheetHandlers\\WSHProps", guid_wsh_shellex
|
||||
)
|
||||
|
||||
|
||||
def Register(klass=PyScript):
|
||||
ret = win32com.server.register.UseCommandLine(
|
||||
klass, finalize_register=DllRegisterServer
|
||||
)
|
||||
return ret
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
Register()
|
||||
@@ -0,0 +1,54 @@
|
||||
# A version of the ActiveScripting engine that enables rexec support
|
||||
# This version supports hosting by IE - however, due to Python's
|
||||
# rexec module being neither completely trusted nor private, it is
|
||||
# *not* enabled by default.
|
||||
# As of Python 2.2, rexec is simply not available - thus, if you use this,
|
||||
# a HTML page can do almost *anything* at all on your machine.
|
||||
|
||||
# You almost certainly do NOT want to use thus!
|
||||
|
||||
import pythoncom
|
||||
from win32com.axscript import axscript
|
||||
|
||||
from . import pyscript
|
||||
|
||||
INTERFACE_USES_DISPEX = 0x00000004 # Object knows to use IDispatchEx
|
||||
INTERFACE_USES_SECURITY_MANAGER = (
|
||||
0x00000008 # Object knows to use IInternetHostSecurityManager
|
||||
)
|
||||
|
||||
|
||||
class PyScriptRExec(pyscript.PyScript):
|
||||
# Setup the auto-registration stuff...
|
||||
_reg_verprogid_ = "Python.AXScript-rexec.2"
|
||||
_reg_progid_ = "Python" # Same ProgID as the standard engine.
|
||||
# _reg_policy_spec_ = default
|
||||
_reg_catids_ = [axscript.CATID_ActiveScript, axscript.CATID_ActiveScriptParse]
|
||||
_reg_desc_ = "Python ActiveX Scripting Engine (with rexec support)"
|
||||
_reg_clsid_ = "{69c2454b-efa2-455b-988c-c3651c4a2f69}"
|
||||
_reg_class_spec_ = "win32com.axscript.client.pyscript_rexec.PyScriptRExec"
|
||||
_reg_remove_keys_ = [(".pys",), ("pysFile",)]
|
||||
_reg_threading_ = "Apartment"
|
||||
|
||||
def _GetSupportedInterfaceSafetyOptions(self):
|
||||
# print(
|
||||
# "**** calling",
|
||||
# pyscript.PyScript._GetSupportedInterfaceSafetyOptions,
|
||||
# "**->",
|
||||
# pyscript.PyScript._GetSupportedInterfaceSafetyOptions(self),
|
||||
# )
|
||||
return (
|
||||
INTERFACE_USES_DISPEX
|
||||
| INTERFACE_USES_SECURITY_MANAGER
|
||||
| axscript.INTERFACESAFE_FOR_UNTRUSTED_DATA
|
||||
| axscript.INTERFACESAFE_FOR_UNTRUSTED_CALLER
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("WARNING: By registering this engine, you are giving remote HTML code")
|
||||
print("the ability to execute *any* code on your system.")
|
||||
print()
|
||||
print("You almost certainly do NOT want to do this.")
|
||||
print("You have been warned, and are doing this at your own (significant) risk")
|
||||
pyscript.Register(PyScriptRExec)
|
||||
@@ -0,0 +1,103 @@
|
||||
"""dynamic dispatch objects for AX Script.
|
||||
|
||||
This is an IDispatch object that a scripting host may use to
|
||||
query and invoke methods on the main script. Not may hosts use
|
||||
this yet, so it is not well tested!
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import types
|
||||
|
||||
import pythoncom
|
||||
import win32com.server.policy
|
||||
import win32com.server.util
|
||||
import winerror
|
||||
from win32com.client import Dispatch
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
debugging = 0
|
||||
|
||||
PyIDispatchType = pythoncom.TypeIIDs[pythoncom.IID_IDispatch]
|
||||
|
||||
# ignore hasattr(obj, "__call__") as this means all COM objects!
|
||||
_CallableTypes = (types.FunctionType, types.MethodType)
|
||||
|
||||
|
||||
class ScriptDispatch:
|
||||
_public_methods_: list[str] = []
|
||||
|
||||
def __init__(self, engine, scriptNamespace):
|
||||
self.engine = engine
|
||||
self.scriptNamespace = scriptNamespace
|
||||
|
||||
def _dynamic_(self, name, lcid, wFlags, args):
|
||||
# Ensure any newly added items are available.
|
||||
self.engine.RegisterNewNamedItems()
|
||||
self.engine.ProcessNewNamedItemsConnections()
|
||||
if wFlags & pythoncom.INVOKE_FUNC:
|
||||
# attempt to call a function
|
||||
try:
|
||||
func = getattr(self.scriptNamespace, name)
|
||||
if not isinstance(func, _CallableTypes):
|
||||
raise AttributeError(name) # Not a function.
|
||||
realArgs = []
|
||||
for arg in args:
|
||||
if isinstance(arg, PyIDispatchType):
|
||||
realArgs.append(Dispatch(arg))
|
||||
else:
|
||||
realArgs.append(arg)
|
||||
# xxx - todo - work out what code block to pass???
|
||||
return self.engine.ApplyInScriptedSection(None, func, tuple(realArgs))
|
||||
|
||||
except AttributeError:
|
||||
if not wFlags & pythoncom.DISPATCH_PROPERTYGET:
|
||||
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
|
||||
if wFlags & pythoncom.DISPATCH_PROPERTYGET:
|
||||
# attempt to get a property
|
||||
try:
|
||||
ret = getattr(self.scriptNamespace, name)
|
||||
if isinstance(ret, _CallableTypes):
|
||||
raise AttributeError(name) # Not a property.
|
||||
except AttributeError:
|
||||
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
|
||||
except COMException as instance:
|
||||
raise
|
||||
except:
|
||||
ret = self.engine.HandleException()
|
||||
return ret
|
||||
|
||||
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
|
||||
|
||||
|
||||
class StrictDynamicPolicy(win32com.server.policy.DynamicPolicy):
|
||||
def _wrap_(self, object):
|
||||
win32com.server.policy.DynamicPolicy._wrap_(self, object)
|
||||
if hasattr(self._obj_, "scriptNamespace"):
|
||||
for name in dir(self._obj_.scriptNamespace):
|
||||
self._dyn_dispid_to_name_[self._getdispid_(name, 0)] = name
|
||||
|
||||
def _getmembername_(self, dispid):
|
||||
try:
|
||||
return str(self._dyn_dispid_to_name_[dispid])
|
||||
except KeyError:
|
||||
raise COMException(scode=winerror.DISP_E_UNKNOWNNAME, desc="Name not found")
|
||||
|
||||
def _getdispid_(self, name, fdex):
|
||||
try:
|
||||
func = getattr(self._obj_.scriptNamespace, str(name))
|
||||
except AttributeError:
|
||||
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
|
||||
# if not isinstance(func, _CallableTypes):
|
||||
return win32com.server.policy.DynamicPolicy._getdispid_(self, name, fdex)
|
||||
|
||||
|
||||
def _wrap(obj):
|
||||
useDispatcher = win32com.server.policy.DispatcherWin32trace if debugging else None
|
||||
return win32com.server.util.wrap(
|
||||
obj, usePolicy=StrictDynamicPolicy, useDispatcher=useDispatcher
|
||||
)
|
||||
|
||||
|
||||
def MakeScriptDispatch(engine, namespace):
|
||||
return _wrap(ScriptDispatch(engine, namespace))
|
||||
@@ -0,0 +1,145 @@
|
||||
import pythoncom
|
||||
import winerror
|
||||
from win32com.axscript import axscript
|
||||
from win32com.server import util
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
|
||||
class AXEngine:
|
||||
def __init__(self, site, engine):
|
||||
self.eScript = self.eParse = self.eSafety = None
|
||||
if isinstance(engine, str):
|
||||
engine = pythoncom.CoCreateInstance(
|
||||
engine, None, pythoncom.CLSCTX_SERVER, pythoncom.IID_IUnknown
|
||||
)
|
||||
|
||||
self.eScript = engine.QueryInterface(axscript.IID_IActiveScript)
|
||||
self.eParse = engine.QueryInterface(axscript.IID_IActiveScriptParse)
|
||||
self.eSafety = engine.QueryInterface(axscript.IID_IObjectSafety)
|
||||
|
||||
self.eScript.SetScriptSite(site)
|
||||
self.eParse.InitNew()
|
||||
|
||||
def __del__(self):
|
||||
self.Close()
|
||||
|
||||
def GetScriptDispatch(self, name=None):
|
||||
return self.eScript.GetScriptDispatch(name)
|
||||
|
||||
def AddNamedItem(self, item, flags):
|
||||
return self.eScript.AddNamedItem(item, flags)
|
||||
|
||||
# Some helpers.
|
||||
def AddCode(self, code, flags=0):
|
||||
self.eParse.ParseScriptText(code, None, None, None, 0, 0, flags)
|
||||
|
||||
def EvalCode(self, code):
|
||||
return self.eParse.ParseScriptText(
|
||||
code, None, None, None, 0, 0, axscript.SCRIPTTEXT_ISEXPRESSION
|
||||
)
|
||||
|
||||
def Start(self):
|
||||
# Should maybe check state?
|
||||
# Do I need to transition through?
|
||||
self.eScript.SetScriptState(axscript.SCRIPTSTATE_STARTED)
|
||||
|
||||
# self.eScript.SetScriptState(axscript.SCRIPTSTATE_CONNECTED)
|
||||
|
||||
def Close(self):
|
||||
if self.eScript:
|
||||
self.eScript.Close()
|
||||
self.eScript = self.eParse = self.eSafety = None
|
||||
|
||||
def SetScriptState(self, state):
|
||||
self.eScript.SetScriptState(state)
|
||||
|
||||
|
||||
IActiveScriptSite_methods = [
|
||||
"GetLCID",
|
||||
"GetItemInfo",
|
||||
"GetDocVersionString",
|
||||
"OnScriptTerminate",
|
||||
"OnStateChange",
|
||||
"OnScriptError",
|
||||
"OnEnterScript",
|
||||
"OnLeaveScript",
|
||||
]
|
||||
|
||||
|
||||
class AXSite:
|
||||
"""An Active Scripting site. A Site can have exactly one engine."""
|
||||
|
||||
_public_methods_ = IActiveScriptSite_methods
|
||||
_com_interfaces_ = [axscript.IID_IActiveScriptSite]
|
||||
|
||||
def __init__(self, objModel={}, engine=None, lcid=0):
|
||||
self.lcid = lcid
|
||||
self.objModel = {}
|
||||
for name, object in objModel.items():
|
||||
# Gregs code did str.lower this - I think that is callers job if he wants!
|
||||
self.objModel[name] = object
|
||||
|
||||
self.engine = None
|
||||
if engine:
|
||||
self._AddEngine(engine)
|
||||
|
||||
def AddEngine(self, engine):
|
||||
"""Adds a new engine to the site.
|
||||
engine can be a string, or a fully wrapped engine object.
|
||||
"""
|
||||
if isinstance(engine, str):
|
||||
newEngine = AXEngine(util.wrap(self), engine)
|
||||
else:
|
||||
newEngine = engine
|
||||
self.engine = newEngine
|
||||
flags = (
|
||||
axscript.SCRIPTITEM_ISVISIBLE
|
||||
| axscript.SCRIPTITEM_NOCODE
|
||||
| axscript.SCRIPTITEM_GLOBALMEMBERS
|
||||
| axscript.SCRIPTITEM_ISPERSISTENT
|
||||
)
|
||||
for name in self.objModel:
|
||||
newEngine.AddNamedItem(name, flags)
|
||||
newEngine.SetScriptState(axscript.SCRIPTSTATE_INITIALIZED)
|
||||
return newEngine
|
||||
|
||||
# B/W compat
|
||||
_AddEngine = AddEngine
|
||||
|
||||
def _Close(self):
|
||||
self.engine.Close()
|
||||
self.objModel = {}
|
||||
|
||||
def GetLCID(self):
|
||||
return self.lcid
|
||||
|
||||
def GetItemInfo(self, name, returnMask):
|
||||
if name not in self.objModel:
|
||||
raise COMException(
|
||||
scode=winerror.TYPE_E_ELEMENTNOTFOUND, desc="item not found"
|
||||
)
|
||||
|
||||
### for now, we don't have any type information
|
||||
|
||||
if returnMask & axscript.SCRIPTINFO_IUNKNOWN:
|
||||
return (self.objModel[name], None)
|
||||
|
||||
return (None, None)
|
||||
|
||||
def GetDocVersionString(self):
|
||||
return "Python AXHost version 1.0"
|
||||
|
||||
def OnScriptTerminate(self, result, excepInfo):
|
||||
pass
|
||||
|
||||
def OnStateChange(self, state):
|
||||
pass
|
||||
|
||||
def OnScriptError(self, errorInterface):
|
||||
return winerror.S_FALSE
|
||||
|
||||
def OnEnterScript(self):
|
||||
pass
|
||||
|
||||
def OnLeaveScript(self):
|
||||
pass
|
||||
@@ -0,0 +1,16 @@
|
||||
def Function(i):
|
||||
Test.Echo(i)
|
||||
|
||||
print(dir())
|
||||
|
||||
a=1
|
||||
b=a
|
||||
c=b # And here is a comment
|
||||
d="A string"
|
||||
print(a)
|
||||
Test.echo("Hello from Python")
|
||||
for i in range(2):
|
||||
Function(i)
|
||||
a = """\
|
||||
A multi-line string!
|
||||
"""
|
||||
@@ -0,0 +1,7 @@
|
||||
a=1
|
||||
b=a
|
||||
Test.Echo "Hello from VBScript"
|
||||
' Here is a comment
|
||||
for i = 1 to 10
|
||||
|
||||
next
|
||||
@@ -0,0 +1,185 @@
|
||||
import sys
|
||||
|
||||
import pythoncom
|
||||
from win32com.axscript import axscript
|
||||
from win32com.axscript.server import axsite
|
||||
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 won't 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
|
||||
"""
|
||||
|
||||
PyScript = """\
|
||||
print("PyScript is being parsed...")\n
|
||||
|
||||
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(f"***** Function call didnt set value correctly {echoer.last!r}")
|
||||
|
||||
if str(ob.prop) != "Property Value":
|
||||
print(f"***** Property Value not correct - {ob.prop!r}")
|
||||
|
||||
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()
|
||||
@@ -0,0 +1,240 @@
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import pythoncom
|
||||
import win32com.server.policy
|
||||
import win32com.test.util
|
||||
from win32com.axscript import axscript
|
||||
from win32com.axscript.server import axsite
|
||||
from win32com.client.dynamic import Dispatch
|
||||
from win32com.server import connect, util
|
||||
|
||||
verbose = "-v" in sys.argv
|
||||
|
||||
|
||||
class MySite(axsite.AXSite):
|
||||
def __init__(self, *args):
|
||||
self.exception_seen = None
|
||||
axsite.AXSite.__init__(self, *args)
|
||||
|
||||
def OnScriptError(self, error):
|
||||
self.exception_seen = exc = error.GetExceptionInfo()
|
||||
context, line, char = error.GetSourcePosition()
|
||||
if not verbose:
|
||||
return
|
||||
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):
|
||||
return util.Collection._NewEnum(self)
|
||||
|
||||
|
||||
class Test:
|
||||
_public_methods_ = ["echo", "fail"]
|
||||
_public_attrs_ = ["collection"]
|
||||
|
||||
def __init__(self):
|
||||
self.verbose = verbose
|
||||
self.collection = util.wrap(MyCollection([1, "Two", 3]))
|
||||
self.last = ""
|
||||
self.fail_called = 0
|
||||
|
||||
# self._connect_server_ = TestConnectServer(self)
|
||||
|
||||
def echo(self, *args):
|
||||
self.last = "".join([str(s) for s in args])
|
||||
if self.verbose:
|
||||
for arg in args:
|
||||
print(arg, end=" ")
|
||||
print()
|
||||
|
||||
def fail(self, *args):
|
||||
print("**** fail() called ***")
|
||||
for arg in args:
|
||||
print(arg, end=" ")
|
||||
print()
|
||||
self.fail_called = 1
|
||||
|
||||
|
||||
# self._connect_server_.Broadcast(last)
|
||||
|
||||
|
||||
#### Connections currently won't 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
|
||||
if test.collection.Item(0) <> 1 then
|
||||
test.fail("Index 0 was wrong")
|
||||
end if
|
||||
if test.collection.Item(1) <> "Two" then
|
||||
test.fail("Index 1 was wrong")
|
||||
end if
|
||||
if test.collection.Item(2) <> 3 then
|
||||
test.fail("Index 2 was wrong")
|
||||
end if
|
||||
num = 0
|
||||
for each item in test.collection
|
||||
num = num + 1
|
||||
next
|
||||
if num <> 3 then
|
||||
test.fail("Collection didn't have 3 items")
|
||||
end if
|
||||
end sub
|
||||
"""
|
||||
PyScript = """\
|
||||
# A unicode \xa9omment.
|
||||
prop = "Property Value"
|
||||
def hello(arg1):
|
||||
test.echo(arg1)
|
||||
|
||||
def testcollection():
|
||||
# test.collection[1] = "New one"
|
||||
got = []
|
||||
for item in test.collection:
|
||||
got.append(item)
|
||||
if got != [1, "Two", 3]:
|
||||
test.fail("Didn't get the collection")
|
||||
pass
|
||||
"""
|
||||
|
||||
ErrScript = """\
|
||||
bad code for everyone!
|
||||
"""
|
||||
|
||||
state_map = {
|
||||
axscript.SCRIPTSTATE_UNINITIALIZED: "SCRIPTSTATE_UNINITIALIZED",
|
||||
axscript.SCRIPTSTATE_INITIALIZED: "SCRIPTSTATE_INITIALIZED",
|
||||
axscript.SCRIPTSTATE_STARTED: "SCRIPTSTATE_STARTED",
|
||||
axscript.SCRIPTSTATE_CONNECTED: "SCRIPTSTATE_CONNECTED",
|
||||
axscript.SCRIPTSTATE_DISCONNECTED: "SCRIPTSTATE_DISCONNECTED",
|
||||
axscript.SCRIPTSTATE_CLOSED: "SCRIPTSTATE_CLOSED",
|
||||
}
|
||||
|
||||
|
||||
def _CheckEngineState(engine, name, state):
|
||||
got = engine.engine.eScript.GetScriptState()
|
||||
if got != state:
|
||||
got_name = state_map.get(got, str(got))
|
||||
state_name = state_map.get(state, str(state))
|
||||
raise RuntimeError(
|
||||
f"Warning - engine {name} has state {got_name}, but expected {state_name}"
|
||||
)
|
||||
|
||||
|
||||
class EngineTester(win32com.test.util.TestCase):
|
||||
def _TestEngine(self, engineName, code, expected_exc=None):
|
||||
echoer = Test()
|
||||
model = {
|
||||
"test": util.wrap(echoer),
|
||||
}
|
||||
site = MySite(model)
|
||||
engine = site._AddEngine(engineName)
|
||||
try:
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_INITIALIZED)
|
||||
engine.AddCode(code)
|
||||
engine.Start()
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_STARTED)
|
||||
self.assertTrue(not echoer.fail_called, "Fail should not have been called")
|
||||
# Now call into the scripts IDispatch
|
||||
ob = Dispatch(engine.GetScriptDispatch())
|
||||
try:
|
||||
ob.hello("Goober")
|
||||
self.assertTrue(
|
||||
expected_exc is None,
|
||||
f"Expected {expected_exc!r}, but no exception seen",
|
||||
)
|
||||
except pythoncom.com_error:
|
||||
if expected_exc is None:
|
||||
self.fail(
|
||||
f"Unexpected failure from script code: {site.exception_seen}"
|
||||
)
|
||||
if expected_exc not in site.exception_seen[2]:
|
||||
self.fail(
|
||||
f"Could not find {expected_exc!r} in {site.exception_seen[2]!r}"
|
||||
)
|
||||
return
|
||||
self.assertEqual(echoer.last, "Goober")
|
||||
|
||||
self.assertEqual(str(ob.prop), "Property Value")
|
||||
ob.testcollection()
|
||||
self.assertTrue(not echoer.fail_called, "Fail should not have been called")
|
||||
|
||||
# Now make sure my engines can evaluate stuff.
|
||||
result = engine.eParse.ParseScriptText(
|
||||
"1+1", None, None, None, 0, 0, axscript.SCRIPTTEXT_ISEXPRESSION
|
||||
)
|
||||
self.assertEqual(result, 2)
|
||||
# re-initialize to make sure it transitions back to initialized again.
|
||||
engine.SetScriptState(axscript.SCRIPTSTATE_INITIALIZED)
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_INITIALIZED)
|
||||
engine.Start()
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_STARTED)
|
||||
|
||||
# Transition back to initialized, then through connected too.
|
||||
engine.SetScriptState(axscript.SCRIPTSTATE_INITIALIZED)
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_INITIALIZED)
|
||||
engine.SetScriptState(axscript.SCRIPTSTATE_CONNECTED)
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_CONNECTED)
|
||||
engine.SetScriptState(axscript.SCRIPTSTATE_INITIALIZED)
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_INITIALIZED)
|
||||
|
||||
engine.SetScriptState(axscript.SCRIPTSTATE_CONNECTED)
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_CONNECTED)
|
||||
engine.SetScriptState(axscript.SCRIPTSTATE_DISCONNECTED)
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_DISCONNECTED)
|
||||
finally:
|
||||
engine.Close()
|
||||
engine = None
|
||||
site = None
|
||||
|
||||
def testVB(self):
|
||||
self._TestEngine("VBScript", VBScript)
|
||||
|
||||
def testPython(self):
|
||||
self._TestEngine("Python", PyScript)
|
||||
|
||||
def testPythonUnicodeError(self):
|
||||
self._TestEngine("Python", PyScript)
|
||||
|
||||
def testVBExceptions(self):
|
||||
self.assertRaises(pythoncom.com_error, self._TestEngine, "VBScript", ErrScript)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,83 @@
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import pythoncom
|
||||
import win32ui
|
||||
from win32com.axscript.server import axsite
|
||||
from win32com.server import util
|
||||
|
||||
version = "0.0.1"
|
||||
|
||||
|
||||
class MySite(axsite.AXSite):
|
||||
def OnScriptError(self, error):
|
||||
print("An error occurred in the Script Code")
|
||||
exc = error.GetExceptionInfo()
|
||||
try:
|
||||
text = error.GetSourceLineText()
|
||||
except:
|
||||
text = "<unknown>"
|
||||
context, line, char = error.GetSourcePosition()
|
||||
print(
|
||||
"Exception: %s (line %d)\n%s\n%s^\n%s"
|
||||
% (exc[1], line, text, " " * (char - 1), exc[2])
|
||||
)
|
||||
|
||||
|
||||
class ObjectModel:
|
||||
_public_methods_ = ["echo", "msgbox"]
|
||||
|
||||
def echo(self, *args):
|
||||
print("".join(map(str, args)))
|
||||
|
||||
def msgbox(self, *args):
|
||||
msg = "".join(map(str, args))
|
||||
win32ui.MessageBox(msg)
|
||||
|
||||
|
||||
def TestEngine():
|
||||
model = {"Test": util.wrap(ObjectModel())}
|
||||
scriptDir = "."
|
||||
site = MySite(model)
|
||||
pyEngine = site._AddEngine("Python")
|
||||
# pyEngine2 = site._AddEngine("Python")
|
||||
vbEngine = site._AddEngine("VBScript")
|
||||
# forthEngine = site._AddEngine("ForthScript")
|
||||
try:
|
||||
# code = open(os.path.join(scriptDir, "debugTest.4ths"),"rb").read()
|
||||
# forthEngine.AddCode(code)
|
||||
code = open(os.path.join(scriptDir, "debugTest.pys"), "rb").read()
|
||||
pyEngine.AddCode(code)
|
||||
code = open(os.path.join(scriptDir, "debugTest.vbs"), "rb").read()
|
||||
vbEngine.AddCode(code)
|
||||
# code = open(os.path.join(scriptDir, "debugTestFail.pys"),"rb").read()
|
||||
# pyEngine2.AddCode(code)
|
||||
|
||||
# from win32com.axdebug import axdebug
|
||||
# sessionProvider=pythoncom.CoCreateInstance(axdebug.CLSID_DefaultDebugSessionProvider,None,pythoncom.CLSCTX_ALL, axdebug.IID_IDebugSessionProvider)
|
||||
# sessionProvider.StartDebugSession(None)
|
||||
|
||||
input("Press enter to continue")
|
||||
# forthEngine.Start()
|
||||
pyEngine.Start() # Actually run the Python code
|
||||
vbEngine.Start() # Actually run the VB code
|
||||
except pythoncom.com_error as details:
|
||||
print(f"Script failed: {details[1]} (0x{details[0]:x})")
|
||||
# Now run the code expected to fail!
|
||||
# try:
|
||||
# pyEngine2.Start() # Actually run the Python code that fails!
|
||||
# print("Script code worked when it should have failed.")
|
||||
# except pythoncom.com_error:
|
||||
# pass
|
||||
|
||||
site._Close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
TestEngine()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
sys.exc_type = sys.exc_value = sys.exc_traceback = None
|
||||
print(pythoncom._GetInterfaceCount(), "com objects still alive")
|
||||
Reference in New Issue
Block a user