|
#include <Misc.au3>
_Singleton("TheNameOfMy")
Opt("RunErrorsFatal", 0)
Opt("WinTitleMatchMode", 2) ;窗口函数在搜索时的标题匹配模式,2为任意子串皆可匹配
;Opt("WinTextMatchMode",2) ;最好不用这句,窗口函数在搜索时的模式,2为快速模式,这个设置会影响搜索的速度和匹配到的数量,快速模式下某些特殊窗口无法找到
Opt("TrayIconHide", 1) ;隐藏托盘区图标
;下面是根据命令行参数来设置常量,---------------
if $CmdLineRaw = "" Then ;如果命令行参数为空
Const $cfgpath = @ScriptDir & "\safecfg.ini" ;则设定常量$cfgpath(这个常量代表配置文件路径)值为程序自身目录下的safecfg.ini
Else
Const $cfgpath = $CmdLine[1] ;否则(就是命令行有参数)就将命令行第1个参数设定为$cfgpath的值,对于这个值是否有效在后面作检测
EndIf ;结束判断,注意if--Then语句,当then 后面只有一条命令/语句时,endif可以省略,但是要求整个判断要在处于一行。当then后面跟两条语句时则(那就不能处于一行了)则then后面必须另起一行,最后加上endif,如果有else则必须也有endif
;以后不再解释EndIf
if $CmdLine[0] < 2 Then ;如果命令行参数小于两个(当然也包括为空)
Const $hkey = IniRead($cfgpath, "程序配置", "热键设置", "") ;读取配置文件的热键赋值给常量$hkey(这个常量是代表热键)这里用到了上面的$cfgpath常量,要注意变量引用的顺序,必须指定后才能在之后引用
Else
Const $hkey = $CmdLine[2] ;否则(就是命令行有两个参数)则$hkey值设为第二参数
EndIf
;下面是致使错误控制,当然无非是找不到配置文件,未设置退出热键-------------------
If not FileExists($cfgpath) Then error("未找到配置文件!") ;直译为如果非$cfgpath代表的文件存在(就是如果文件不存在)则调用函数error(自定的函数,后面会解释)并传递值未找到配置文件
;error()这个函数是自己写的,执行时会以对话框显示传递到它的信息,并且退出程序
;这儿就可以不用endif
If $hkey = "" Then error("未设置热键!") ;如果$hkey数据为空则调用函数error并传递原因是未设置热键,当然未设置热键并非是致命错误,把这条删掉程序也可以运行,只是未指定热键你就无法退出了,只能用任务管理器了
HotkeySet($hkey, "_exit") ;设置一个热键,当按下$hkey代表的键位时,调用_exit函数(这个函数就是退出程序)
;目前并未严谨地判断热键设置是否合法,因为这不好控制,而且没有多大实际意义,只要你设置正确就行,就算设置不正确,也无非是不能退出,你肯定能找到原因
;下面是设置日志的变量-------------------
if IniRead($cfgpath, "程序配置", "日志路径", "") = "" Then ;如果配置文件中日志路径为空
Const $logfilename = @ScriptDir & "\safelog.log" ;则设置$logfilename为程序自身目录下的safelog.log(当然写入日志时没有此文件会自动创建)
Else
Const $logfilename = iniread($cfgpath, "程序配置", "日志路径", "") ;否则(配置文件中指定了日志路径)设置$logfilename为指定的值
EndIf
Global $logfalse = 1 ;作一个标记,记录日志是否可以成功写入,初始为1,当遇到错误时变为0,以后不再显示出错信息
$msg = iniread($cfgpath, "程序配置", "弹出消息", "") ;读取配置文件中弹出消息的设置值赋给$msg,(下面会根据$msg这个变量值决定是否写入日志)
;以下是修改墙纸
$dskpic = IniRead($cfgpath, "程序配置", "桌面墙纸", "")
if $dskpic <> "" Then
If StringLower(StringRight($dskpic, 3)) = "bmp" Then ;目前只支持BMP格式,要想支持JPG也不难,但是完全没有必要,因为windows实际只支持bmp
If FileExists($dskpic) Then ;确认墙纸文件存在
DllCall("user32", "int", "SystemParametersInfo", "int", 20, "int", 0, "str", $dskpic, "int", 0) ;调用windowsAPI设置墙纸
EndIf
EndIf
EndIf
;----------------------------------------
;下面几组是读取配置文件里几个主要段的所有值保存到一个数组变量中,防止程序运行时更改配置文件,也避免重复读取配置文件加重系统负担
$s_windows = 1 ;这个变量是自己定义的,名字随意,初始值为1,当作一个标记来用,下面会有详细解释
$c_windows = IniReadSection($cfgpath, "禁止窗口") ;读取禁止窗口这个字段里所有的项,
if @error then $s_windows = 0 ;这里用上了刚才定义的$s_windows这个标记,就是当读取禁止窗口出现错误时(无法读取或内容为空)把值设为0
;----------------------------------------
$s_pro = 1 ;这里和上面都相同,不再解释了,相信能看明白
$c_pro = IniReadSection($cfgpath, "禁止进程")
if @error then $s_pro = 0
;----------------------------------------
$s_runpro = 1
$c_runpro = IniReadSection($cfgpath, "监视进程")
if @error then $s_runpro = 0
;----------------------------------------
$s_mustpro = 1
$c_mustpro = IniReadSection($cfgpath, "必须进程")
if @error then $s_mustpro = 0
;这是应网友要求增加的ARP绑定,这部分内容不再作解释,关于数组在下面有解释
$arp = IniReadSection($cfgpath, "arp绑定")
if not @error Then
for $a = 1 to $arp[0][0]
If chkarp($arp[$a][0], $arp[$a][1]) = True Then ;这段大家参考完下面再看这段就可以理解了,chkarp()是自己写的初步检测IP和mac格式的,只是初步
RunWait(@ComSpec & " /c " & "arp -s " & $arp[$a][0] & " " & $arp[$a][1], "", @SW_HIDE) ;运行ARP绑定,隐藏窗口
Else
ToolTip("字段ARP绑定中" & $arp[$a][0] & "不是合法IP或对应mac格式不正确", 0, 0)
Sleep(2000) ;等待提示显示2秒,sleep单位是毫秒,1000毫秒=1秒
ToolTip("", 0, 0) ;关闭提示
EndIf
Next
EndIf
;下面会用上面的标记,来确定配置文件里这些内容为空时报错
if $s_windows = 0 And $s_pro = 0 And $s_runpro = 0 And $s_mustpro = 0 Then error("配置文件的项目为空或无法读取!程序退出!") ;不用解释了吧?
;-------------------------------------------------
;---------正戏上场了,这才是程序的主体------------
;-------------------------------------------------
While 1 ;这是框架,while是条件循环,就是当满足某条件时会一直循环下去,while 1 就是一直循环下去,相当于 while 1=1
;以下是分组判断循环
;第一个是禁止窗口
if $s_windows = 1 then ;如果$s_windows值是1(看到前面的标记有用处了吧,当它为1时就是禁止窗口里有数据,当然为0没有数据也就不会循环了)
For $i = 1 To $c_windows[0][0] ;for语句是计次循环,就是$i(也是一个重要指针)初始值为1 循环到$c_windows[0][0]次 (上面我说过把禁止窗口里所有项读到了一个数组变量里,数组变量[0][0]代表了共有多少个值也就是定义了几个要禁止的窗口)
;这里有必要解释一下数组,数组就是一个数据(格式为xx或XX,yy也可是xx=yy)的集合,就像数据库中的表一样,其中[0]或[0][0]表示记录总数,[1][0]表示第一个数据左边,[1][1]表示第一个数据右边,以此类推
If StringInStr(WinGetTitle(""), $c_windows[$i][0]) > 0 Then ;如果$c_windows数组中第$i个值是当前窗口标题(WinGetTitle)的子串(不区分大小写)(就是标题中包含被禁止的内容)
;-----这句要自己理解,其实也很简单,就是StringInStr(总字符串,要匹配的子串)默认不区分大小写,总字符串是当前窗口标题,要匹配的子串就是配置文件中定义的,返回值为子串的位置,代表匹配成功(标题包含禁止内容)失败返回0
WinClose("") ;关闭窗口
if $msg = 1 Then MsgBox(0, "警告!", "对不起!您打开的窗口中包含(" & $c_windows[$i][0] & "),该窗口已被管理员禁止!", 2) ;如果$msg=1就是显示消息,则弹出对话框显示消息,2秒后自动关闭
writelog("在计算机" & @ComputerName & "上发现非法窗口:" & $c_windows[$i][0]) ;写入日志,本来可以设为能不写,不过还是写日志好,如果你想手动设是否与日志,再加一条就行了,相信你看完应该可以修改了吧
endif
Next
Endif
;禁止窗口完毕,下面是禁止进程,有了上面的解释,下面应该不用太多,简单解释一下吧
If $s_pro = 1 Then
for $i = 1 to $c_pro[0][0] ;循环从1到禁止进程的数量
If ProcessExists($c_pro[$i][0]) Then ;查找指定进程是否存在,成功返回进程Pid失败返回0,这句其实是 processexists($xxx) >0,不过默认为真所以省略
ProcessClose($c_pro[$i][0]) ;关闭进程,
if $msg = 1 Then MsgBox(0, "警告!", "对不起!进程(" & $c_pro[$i][0] & ")已被管理员禁止!", 2)
writelog("在计算机" & @ComputerName & "上发现非法[进程]:" & $c_pro[$i][0])
endif
Sleep(15)
Next
;禁止窗口完毕,下面是监视进程
EndIf
If $s_runpro = 1 Then
For $i = 1 to $c_runpro[0][0]
If Not ProcessExists($c_runpro[$i][0]) Then ;同上句差不多,这句只是条件变为假,就是进程中不存在指定进程时,
Run($c_runpro[$i][1], "", @SW_HIDE) ;启动进程,注意这句变成了右边的值(就是程序路径)
If @error Then Run(@ComSpec & " /c " & $c_runpro[$i][1], "", @SW_HIDE);这句是如果运行失败,则尝试使用cmd来启动
Sleep(5000) ;等待5秒种,因为某些程序启动需要时间才能出现进程
EndIf
Next
EndIf
;这是必须进程,和上面基本一致,只是操作变成了重启计算机
If $s_mustpro = 1 Then
for $i = 1 to $c_mustpro[0][0]
If Not ProcessExists($c_mustpro[$i][0]) Then Shutdown(6)
Next
EndIf
;完毕
WEnd ;主体循环结束
;--------------------------
;以下是函数区域------------
Func _exit() ;这不用解释了吧
exit
EndFunc ;==>_exit
Func writelog($s) ;日志函数
If Not $logfalse = 0 Then
$logfile = FileOpen($logfilename, 1) ;以写入模式打开文件句柄,供后面写入
if $logfile = -1 Then ;如果打开文件失败
ToolTip("日志文件写入失败!", 0, 0)
Sleep(2000)
ToolTip("", 0, 0)
$logfalse = 0
Else
$time1 = @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & " "
FileWriteLine($logfile, $time1 & $s)
EndIf
FileClose($logfile)
EndIf
EndFunc ;==>writelog
Func error($s)
MsgBox(0, "错误!", $s)
Exit
EndFunc ;==>error
;初步检测IP和Mac地址是否合法,若要详细精确地控制,则自己修改即可,下面只检测IP地址是否全为数字,是否以.分为四段,Mac地址是否为6段,并未判断每段是否大于255
;如果想精确控制,只需判断一下IP数组中每个值是否大于255,再检测Mac地址是否每段为2个十六进制字符即可
Func chkarp($s, $ss)
$true = True
$sip = StringSplit($s, ".")
$smac = StringSplit($ss, "-")
if Not $sip[0] = 4 Then $true = False
if Not IsNumber(stringreplace($s, ".", "")) = 0 then $true = False
if Not $smac[0] = 6 then $true = False
Return $true
EndFunc ;==>chkarp |
|