2012年2月19日星期日

ACM在线评判系统的原理

 

一、自动编译

在程序中通过启动编译器进程对源文件进行编译,通过获取编译器进程的错误输出流和标准输出流对象,可以获取编译器的输出,判断是否有编译错误发生,同时,再通过检查源文件目录下有无生成的可执行文件或者class文件,可判断最后的连接是否成功

二、运行和判断核心

如果自动编译成功,则需要根据预定义的测试用例对生成的可执行文件进行判断。过程大致如下:

1 主程序

1.1 在主程序中输入可执行文件名,相关的命令行参数,测试用例的个数,测试用例的执行时间限制,内存使用限制,测试用例文件名信息(输入文件和输出文件必须是成对出现的);

1.2 创建RunCmd对象,通过构造方法的参数将第一步输入的数据传递给RunCmd对象,启动RunCmd的方法doWork作为线程体进行评判。

2 线程RunCmd(doWork)

2.1 创建一个新的进程,相关参数为第一步中的可执行文件名和相关的命令行参数,并设置进程的输入输出和标准错误输出的重定向

2.2 启动进程,获取其标准输入流对象

2.3 打开一个测试用例输入文件,将其中的内容写入到2.2启动的进程的标准输入

2.4 获取进程的内存使用大小

2.5 线程睡眠一段时间(长度为测试用例的最长执行时间限制)

2.6 如果进程未结束,则杀死进程,将超时的代码写到标准输出,线程返回

2.7 如果内存使用超过限制,则将Time Limit Exceeded的代码写到标准输出,线程返回

2.8 获取标准错误输出和标准输出的内容

2.8.1 如果进程返回代码不为0或标准错误输出内容不为空,则将Run Time Error的代码写到标准输出,线程返回

2.8.2 将获得的输出结果与测试用例中的输出文件进行比较,将返回Wrong Answer,Accepted或者Presentation Error的代码

2.8.3 输出执行时间、内存大小等信息到标准输出

2.9 如果在执行过程中遇到内存不足或其他异常,则输出system error的代码或者Output Limit Exceeded的代码

在这个核心的基础上,很容易就可以开发出ACM OJ系统,在线考试系统,实验自动批改的系统等

使用AutoIT进行AutoCAD2006的批量自动注册

 

在机房管理中,有时需要对软件注册,而AutoDesk和Adobe的软件在注册时很蛋疼,每台机器都必须单独对软件进行注册,系统克隆和硬件同传系统是没用的,所以用AutoIT做了一个尝试,可以扩展到类似的软件注册过程中


#include <ie.au3>


Run("C:\\Program Files\\AutoCAD 2006\\acad.exe")
WinWaitActive("AutoCAD 2006 产品激活")
Send("{ENTER}")
_IELoadWait($oIE)
Sleep(5000)
;Get Request Code
$oIE=_IEAttach("现在注册","Embedded")
_IELoadWait($oIE)
$s=_IEBodyReadText($oIE)
$s=StringRegExpReplace($s,"(\r\n)"," ")
$s1=StringRegExp($s,"([\w\d]{4}\s[\w\d]{4}\s[\w\d]{4}\s[\w\d]{4}\s[\w\d]{4}\s[\w\d]{4}\s[\w\d]{4})",1)
if @error=0 Then
    $requestCode=$s1[0]
Else
    MsgBox(0,"","error")
EndIf
Send("{TAB}{DOWN}{TAB}{TAB}{TAB}{ENTER}")
_IELoadWait($oIE)
Sleep(5000)
Send("{DOWN}{TAB}")


;;run keygen and get authenticate code
Run("@keygen.exe")
WinWaitActive("Autodesk AutoCAD 2006 keygen by AGAIN")
Send($requestCode)
$AuthenticateCode=ControlGetText("Autodesk AutoCAD 2006 keygen by AGAIN","","Edit2")
WinClose("Autodesk AutoCAD 2006 keygen by AGAIN")
;;

WinActivate("AutoCAD 2006")
Send($AuthenticateCode)
Send("{TAB}{TAB}{Enter}")
_IELoadWait($oIE)
Sleep(1000)
Send("{TAB}{TAB}{TAB}{Enter}")
Sleep(30000)

WinClose("AutoCAD 2006")

使用AutoIT编写的常熟理工学院-锐捷VPN登录器

首先要使用IE正常登录一次VPN,目的是安装SSL VPN的浏览器插件,因为这个登录器的目的是隐藏IE窗口进行登录,这样不要一直保持一个打开的浏览器窗口。

代码如下:

#include <ie.au3>
#include <array.au3>
#include <date.au3>
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <GuiEdit.au3>
#include <GuiListBox.au3>
#include <base64.au3>
#include <winapi.au3>

Global $oIE,$oFlag
$oFlag=False

Opt("TrayMenuMode", 1)
;Opt("TrayOnEventMode", 1) ;响应托盘事件
Opt("WinTitleMatchMode", 2) ;匹配任意位置字符串

#Region ### START Koda GUI section ### Form=D:\Tools\KodaFormDesigner\Forms\RgVPN.kxf
$Form1 = GUICreate("RGVPN-锐捷VPN登录器", 323, 109, 192, 124)
$Label1 = GUICtrlCreateLabel("用户名", 16, 12, 40, 17)
$txtUsername = GUICtrlCreateInput("", 72, 10, 129, 21)
$Label2 = GUICtrlCreateLabel("密码", 16, 40, 28, 17)
$txtPassword = GUICtrlCreateInput("", 72, 38, 129, 21, BitOR($GUI_SS_DEFAULT_INPUT,$ES_PASSWORD))
$btnLogin = GUICtrlCreateButton("登录", 224, 8, 73, 25)
$BtnLogout = GUICtrlCreateButton("注销", 224, 36, 73, 25)
$Label3 = GUICtrlCreateLabel("验证码", 16, 72, 40, 17)
$txtVCode = GUICtrlCreateInput("", 72, 70, 57, 21)
$Pic1 = GUICtrlCreatePic("", 136, 72, 60, 20)
$btnRefresh = GUICtrlCreateButton("看不清?", 208, 72, 89, 25)

TraySetIcon("", -1)
TraySetClick(64)
$MenuItem1 = TrayCreateItem("恢复窗口")
$MenuItem2 = TrayCreateItem("退出")
$MenuItem3 = TrayCreateItem("关于")
;TraySetOnEvent($MenuItem1,restore)
;TraySetOnEvent($MenuItem2,quit)
;TraySetOnEvent($MenuItem3,about)
TraySetState()
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

GUICtrlSetState($BtnLogout,$GUI_DISABLE)
GUICtrlSetState($BtnLogin,$GUI_ENABLE)
GUICtrlSetState($BtnRefresh,$GUI_ENABLE)

LoadHomePage()

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            if $oFlag=True Then
                Run("cmd /c start close.exe")
                Sleep(1000)
                _IELinkClickByText($oIE,"注    销")
            EndIf
            _IEErrorHandlerDeRegister()
            _IEQuit($oIE)
            Exit

        Case $GUI_EVENT_MINIMIZE
            GUISetState(@SW_HIDE)

        Case $btnRefresh
            _IENavigate($oIE,"
https://61.155.18.8/",1)
            _IELoadWait($oIE)
            Sleep(300)
            $oIE.document.getElementById("overridelink").Click
            _IELoadWait($oIE)
            Sleep(300)
            $oImg = _IEImgGetCollection ($oIE, 8)
            $oPic = $oIE.Document.body.createControlRange()
            $oPic.Add($oImg)
            $oPic.execCommand("Copy")
            $bmp = ClipGet()
            GUICtrlSetImage($pic1,$bmp)

        Case $btnLogin
            GUICtrlSetState($BtnLogout,$GUI_DISABLE)
            GUICtrlSetState($BtnLogin,$GUI_DISABLE)
            GUICtrlSetState($BtnRefresh,$GUI_DISABLE)
            $formUsername=$oIE.document.getElementById("username")
            $formPasswd=$oIE.document.getElementById("passwd")
            $chkCode=$oIE.document.getElementById("chkCode")
            $username=_GUICtrlEdit_GetText($txtUsername)
            $password=_GUICtrlEdit_GetText($txtPassword)
            $vcode=_GUICtrlEdit_GetText($txtVCode)
            if $username<>"" AND $password<>"" AND $vcode<>"" Then
                _IEFormElementSetValue($formUsername,$username)
                _IEFormElementSetValue($formPasswd,$password)
                _IEFormElementSetValue($chkCode,$vcode)
                $oForm=_IEFormGetObjByName($oIE,"Login")
                $oSubmit=_IEFormElementGetObjByName($oForm,"submit")
                _IEAction($oSubmit,"click")
                _IELoadWait($oIE)
                Sleep(300)
                Local $str=$oIE.Document.body.innerHtml
                Local $b=StringRegExp($str,"重新登录",1)
                if @error=0 Then
                    GUICtrlSetState($BtnLogout,$GUI_ENABLE)
                    GUICtrlSetState($BtnRefresh,$GUI_DISABLE)
                    GUICtrlSetState($BtnLogin,$GUI_DISABLE)
                    Sleep(20000)
                    MsgBox(0,"VPN","登录成功")
                    $oFlag=True
                Else
                    MsgBox(0,"VPN","登录失败")
                    GUICtrlSetState($BtnLogout,$GUI_DISABLE)
                    GUICtrlSetState($BtnLogin,$GUI_ENABLE)
                    GUICtrlSetState($BtnRefresh,$GUI_ENABLE)
                EndIf
            Else
                GUICtrlSetState($BtnLogout,$GUI_DISABLE)
                GUICtrlSetState($BtnLogin,$GUI_ENABLE)
                GUICtrlSetState($BtnRefresh,$GUI_ENABLE)
            EndIf

        Case $BtnLogout
            Run("cmd /c start close.exe")
            Sleep(2000)
            _IELinkClickByText($oIE,"注    销")
            _IEErrorHandlerDeRegister()
            ;_IEQuit($oIE)
            Exit

    EndSwitch
    $msg = TrayGetMsg()
    Select
        Case $msg = $MenuItem1
            GUISetState(@SW_SHOWNORMAL)

        Case $msg = $MenuItem2
            quit()

        Case $msg = $MenuItem3
            aboutme()
    EndSelect
WEnd

Func restore()
    GUISetState(@SW_RESTORE)
EndFunc

Func quit()
    if $oFlag=True Then
        Run("cmd /c start close.exe")
        Sleep(2000)
        _IELinkClickByText($oIE,"注    销")
    EndIf
    _IEErrorHandlerDeRegister()
    ;_IEQuit($oIE)
    Exit
EndFunc

Func aboutme()
    MsgBox(0,"锐捷VPN拨号器","常熟理工学院计算机学院 沈健(jimshen@gmail.com,QQ:3262743)版权所有")
EndFunc


Func LoadHomePage()
    _IEErrorHandlerRegister("MyErrFunc")
    $oIE=_IECreate("
https://61.155.18.8/",0,0,1,0)
    _IELoadWait($oIE)
    Sleep(300)
    $oIE.document.getElementById("overridelink").Click
    _IELoadWait($oIE)
    Sleep(300)
    $oImg = _IEImgGetCollection ($oIE, 8)
    $oPic = $oIE.Document.body.createControlRange()
    $oPic.Add($oImg)
    $oPic.execCommand("Copy",False)
    $bmp = ClipGet()
    GUICtrlSetImage($pic1,$bmp)
EndFunc

Func MyErrFunc()
    ; Important: the error object variable MUST be named $oIEErrorHandler
    Local $ErrorScriptline = $oIEErrorHandler.scriptline
    Local $ErrorNumber = $oIEErrorHandler.number
    Local $ErrorNumberHex = Hex($oIEErrorHandler.number, 8)
    Local $ErrorDescription = StringStripWS($oIEErrorHandler.description, 2)
    Local $ErrorWinDescription = StringStripWS($oIEErrorHandler.WinDescription, 2)
    Local $ErrorSource = $oIEErrorHandler.Source
    Local $ErrorHelpFile = $oIEErrorHandler.HelpFile
    Local $ErrorHelpContext = $oIEErrorHandler.HelpContext
    Local $ErrorLastDllError = $oIEErrorHandler.LastDllError
    Local $ErrorOutput = ""
    $ErrorOutput &= "--> COM Error Encountered in " & @ScriptName & @CR
    $ErrorOutput &= "----> $ErrorScriptline = " & $ErrorScriptline & @CR
    $ErrorOutput &= "----> $ErrorNumberHex = " & $ErrorNumberHex & @CR
    $ErrorOutput &= "----> $ErrorNumber = " & $ErrorNumber & @CR
    $ErrorOutput &= "----> $ErrorWinDescription = " & $ErrorWinDescription & @CR
    $ErrorOutput &= "----> $ErrorDescription = " & $ErrorDescription & @CR
    $ErrorOutput &= "----> $ErrorSource = " & $ErrorSource & @CR
    $ErrorOutput &= "----> $ErrorHelpFile = " & $ErrorHelpFile & @CR
    $ErrorOutput &= "----> $ErrorHelpContext = " & $ErrorHelpContext & @CR
    $ErrorOutput &= "----> $ErrorLastDllError = " & $ErrorLastDllError
    ;MsgBox(0, "COM Error", $ErrorOutput)
    SetError(1)
    Return
EndFunc

在运行的过程中IE窗口弹出的消息框,通过另一个进程来自动关闭

#include <IE.au3>

while true
    WinWaitActive("来自网页的消息","")
    If WinActive("来自网页的消息","") Then
        Send("{ENTER}")
        ExitLoop
    endif
wend

while true
    WinWaitActive("Windows Internet Explorer","")
    If WinActive("Windows Internet Explorer","") Then
        Send("{ENTER}")
        ExitLoop
    endif
wend

Exit

在InnoSetup中检测和安装.NET Framework和MySQL Connector/NET

 

[Files]
Source: "D:\VOS\share\tncs\dotnetfx.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall
Source: "D:\VOS\share\tncs\mysql-connector-net-6.4.3.msi"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall 
; 注意: 不要在任何共享系统文件上使用“Flags: ignoreversion”

[Run]
Filename: "{tmp}\dotnetfx.exe"; Parameters: “/Q /NORESTART”; Check: IsFramework20Installed; Flags: runhidden shellexec waituntilterminated hidewizard;
Filename: "msiexec.exe"; Parameters: "/i ""{tmp}\mysql-connector-net-6.4.3.msi"""; Check: IsMysqlConnectorNetInstalled; Flags: hidewizard

[Code]  
function IsFramework20Installed():Boolean;
begin
    Result := not RegKeyExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\.NetFramework\Policy\v2.0');
end;

function IsMysqlConnectorNetInstalled():Boolean;
begin
    Result := not RegKeyExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\MySQL AB\MySQL Connector/Net');
end;