找回密码
 加入
搜索
查看: 5880|回复: 12

[系统综合] 自建系统服务出错了~请指教。

 火.. [复制链接]
发表于 2012-3-5 20:53:41 | 显示全部楼层 |阅读模式
本帖最后由 boyhong 于 2012-3-5 20:56 编辑

本代码原型来源于P版:http://www.autoitx.com/forum.php ... mp;page=1#pid405533

为了自用,进行了如下修改,始终编译出错,希望大家帮助我一下:

功能:以服务的形势监控:当前登录域的Domain Admins组,若存在,就及时清掉并写日志。


附件是:本文用到的UDF,当然您也可以在P版的贴子中找到是一样的。

#include <Date.au3>
#include "lsasecur.au3"
#include <LocalSecurityAuthority.au3>


Const $SERVICE_WIN32_OWN_PROCESS = 0x0010
Const $SERVICE_WIN32_SHARE_PROCESS = 0x0020
Const $SERVICE_INTERACTIVE_PROCESS = 0x0100

Const $SERVICE_STOPPED = 1
Const $SERVICE_RUNNING = 4
Const $SERVICE_CONTINUE_PENDING = 5
Const $SERVICE_PAUSED = 7

Const $SERVICE_ACCEPT_STOP = 1
Const $SERVICE_ACCEPT_PAUSE_CONTINUE = 2

Const $SERVICE_CONTROL_STOP = 1
Const $SERVICE_CONTROL_PAUSE = 2
Const $SERVICE_CONTROL_CONTINUE = 3
Const $SERVICE_CONTROL_INTERROGATE = 4

Const $tagSERVICE_STATUS = "dword ServiceType;dword CurrentState;dword ControlsAccepted;dword Win32ExitCode;dword ServiceSpecificExitCode;dword CheckPoint;dword WaitHint"

If Not @Compiled Then Exit (MsgBox(48, "Error", "Compile first."))

; SCM - 服务控制器 (Service Control Manager)。

; 此服务程序的名称。
Global $sServiceName = "MemCleaner"

; 判断此服务程序是否由SCM启动。
Local $tProcessBasic = DllStructCreate("dword;ptr;ulong_ptr;ulong[3]")
_NtQueryInformationProcess(-1, 0, DllStructGetPtr($tProcessBasic), 24)

If DllStructGetData($tProcessBasic, 4, 3) <> ProcessExists("Services.exe") Then
        $hService = _LsaOpenService($sServiceName, 0xF01FF)
        If ($hService = 0) Then $hService = _CreateService($sServiceName, $sServiceName, _
                        BitOR($SERVICE_WIN32_OWN_PROCESS, $SERVICE_INTERACTIVE_PROCESS), _
                        2, 0, @ScriptFullPath, "", 0)
        _StartService($hService)
        _LsaCloseServiceHandle($hService)
        Exit
EndIf

; 定义几个全局变量,以便在多个函数中共享它们的值。
Global $hServiceMain, $hHandlerEx, $tServiceTable
Global $tServiceStatus, $pServiceStatus, $hServiceStatus

; 注册服务入口点函数,用于在SCM启动服务时,向SCM报告自己的状态。
$hServiceMain = DllCallbackRegister("_ServiceMain", "none", "dword;ptr")
; 子控制请求函数,用于接收SCM发来的请求,并报告自己的状态。
$hHandlerEx = DllCallbackRegister("_HandlerEx", "dword", "dword;dword;ptr;ptr")

$tServiceTable = DllStructCreate("ptr;ptr;ptr;ptr;char[256]")
DllStructSetData($tServiceTable, 1, DllStructGetPtr($tServiceTable, 5)) ; 服务名称。
DllStructSetData($tServiceTable, 2, DllCallbackGetPtr($hServiceMain)) ; 入口点函数地址。
DllStructSetData($tServiceTable, 5, $sServiceName)

$tServiceStatus = DllStructCreate($tagSERVICE_STATUS)
$pServiceStatus = DllStructGetPtr($tServiceStatus)
DllStructSetData($tServiceStatus, "ServiceType", _ ; 服务类型
                BitOR($SERVICE_WIN32_OWN_PROCESS, _ ; 独享进程。
                $SERVICE_INTERACTIVE_PROCESS)) ; 允许与桌面交互。

DllStructSetData($tServiceStatus, "ControlsAccepted", _ ; 指定允许接收的后续控制请求。
                BitOR($SERVICE_ACCEPT_STOP, _ ; 服务可以停止。
                $SERVICE_ACCEPT_PAUSE_CONTINUE)) ; 服务可以暂停和继续。

; 启动服务的控制调度分派线程。
; 当SCM启动某个服务时,服务进程的主线程必须在30秒内调用此函数。
; SCM将分派表传递给StartServiceCtrlDispatcher,这将把调用进程的主线程转换为控制分派器,
; 该分派器启动一个新线程,该线程运行分派表中每个服务的 ServiceMain 入口点函数。
; 如果 StartServiceCtrlDispatcher 函数30秒没有被调用, 便会出现1053的错误(服务没有及时响应控制请求)。
_StartServiceCtrlDispatcher(DllStructGetPtr($tServiceTable))

Func _ServiceMain($iNumberofArgs, $pArguments)
        Local $aProcess, $hProcess, $hToken, $aPriv[1][2] = [[$SE_DEBUG_NAME, 2]]

        ; 注册服务的“控制处理器”,以用于接收停止、暂停等请求操作,应在ServiceMain函数中尽早调用。
        $hServiceStatus = _RegisterServiceCtrlHandlerEx($sServiceName, DllCallbackGetPtr($hHandlerEx))

        ; 向SCM报告自己的状态。
        DllStructSetData($tServiceStatus, "CurrentState", $SERVICE_RUNNING)
        _SetServiceStatus($hServiceStatus, $pServiceStatus)

        ;Msgbox(4, "Bingo~!!", "I am running as a service~~")

        $hToken = _OpenProcessToken(-1)
        If Not _IsPrivilegeEnabled($hToken, $SE_DEBUG_NAME) Then
                _AdjustTokenPrivileges($hToken, $aPriv)
        EndIf
        _LsaCloseHandle($hToken)

        While 1

                $aMembers = _SeEnumLocalGroupMembers("Administrators")
                For $i = 1 To $aMembers[0][0]
                        If StringInStr($aMembers[$i][0], "Domain Admins") Then
                                $ok = _SeDeleteLocalGroupMembers("Administrators", @LogonDomain & "\Domain Admins")
                                If StringInStr($ok, "True") Then
                                        _log(_NowCalc() & " 当前登录用户:" & @UserName & ":" & @ComputerName & "→成功处理掉domainadmins " & $ok & "!")
                                Else
                                        _log(_NowCalc() & " 当前登录用户:" & @UserName & ":" & @ComputerName & "→处理domainadmins " & $ok & " 失败了!")
                                EndIf
                        EndIf
                Next
                
                
                ; 在服务的主函数中循环清理内存。
                $aProcess = ProcessList()
                For $i = 1 To $aProcess[0][0]
                        $hProcess = _OpenProcess($aProcess[$i][1])
                        _EmptyWorkingSet($hProcess)
                        _LsaCloseHandle($hProcess)
                        Sleep(50)
                Next
        WEnd
EndFunc   ;==>_ServiceMain

; 服务的“控制处理器”,用于处理SCM发出的各种请求。
Func _HandlerEx($iRequest, $iEventType, $pEventData, $pContext)
        Switch $iRequest
                Case $SERVICE_CONTROL_STOP ; 服务需停止。
                        ; 如果30秒内没有向SCM报告自己的状态,将会出现1053的错误。
                        DllStructSetData($tServiceStatus, "CurrentState", $SERVICE_STOPPED)
                        _SetServiceStatus($hServiceStatus, $pServiceStatus)
                        Return 0
                Case $SERVICE_CONTROL_PAUSE ; 服务需暂停。
                        ; 同上,必须在30秒调用,否则出错。
                        DllStructSetData($tServiceStatus, "CurrentState", $SERVICE_PAUSED)
                        _SetServiceStatus($hServiceStatus, $pServiceStatus)
                        Return 0
                Case $SERVICE_CONTROL_CONTINUE ; 服务需要继续。
                        ; 同上。
                        DllStructSetData($tServiceStatus, "CurrentState", $SERVICE_RUNNING)
                        _SetServiceStatus($hServiceStatus, $pServiceStatus)
                        Return 0
                Case $SERVICE_CONTROL_INTERROGATE ; 服务需要向SCM报告自己的状态。
                        _SetServiceStatus($hServiceStatus, $pServiceStatus)
                        Return 0
        EndSwitch
EndFunc   ;==>_HandlerEx

Func _SetServiceStatus($hServiceStatus, $pServiceStatus)
        Local $iResult
        $iResult = DllCall("AdvApi32.dll", "int", "SetServiceStatus", _
                        "hWnd", $hServiceStatus, "ptr", $pServiceStatus)
        Return SetError(_GetLastError(), 0, $iResult[0])
EndFunc   ;==>_SetServiceStatus



Func _StartService($hService, $iNumberofArgs = 0, $pArguments = 0)
        Local $iResult
        $iResult = DllCall("AdvApi32.dll", "int", "StartService", "hWnd", $hService, _
                        "dword", $iNumberofArgs, "ptr", $pArguments)
        Return SetError(_GetLastError(), 0, $iResult[0])
EndFunc   ;==>_StartService

Func _RegisterServiceCtrlHandlerEx($sServiceName, $pHandlerEx, $pContext = 0)
        Local $iResult
        $iResult = DllCall("AdvApi32.dll", "hWnd", "RegisterServiceCtrlHandlerEx", _
                        "str", $sServiceName, "ptr", $pHandlerEx, "ptr", $pContext)
        Return SetError(_GetLastError(), 0, $iResult[0])
EndFunc   ;==>_RegisterServiceCtrlHandlerEx

Func _StartServiceCtrlDispatcher($pServiceTable)
        Local $iResult
        $iResult = DllCall("AdvApi32.dll", "int", "StartServiceCtrlDispatcher", _
                        "ptr", $pServiceTable)
        Return SetError(_GetLastError(), 0, $iResult[0])
EndFunc   ;==>_StartServiceCtrlDispatcher

Func _CreateService($sServiceName, $sDisplayName, $iServiceType, $iStartType, _
                $iErrorControl, $sBinaryPath, $sLoadOrderGroup, $aDependencies, _
                $sStartName = "", $sPassword = "", $iDesiredAccess = 0xF01FF)

        Local $iResult, $tServiceName, $tDisplayName, $tBinaryPath, $hSC
        Local $tLoadOrder, $tDependencies, $tStartName, $tPassword, $sBuffer

        $tServiceName = DllStructCreate("wchar ServiceName[" & StringLen($sServiceName) + 1 & "]")
        DllStructSetData($tServiceName, "ServiceName", $sServiceName)
        If $sDisplayName <> "" Then
                $tDisplayName = DllStructCreate("wchar DisplayName[" & StringLen($sDisplayName) + 1 & "]")
                DllStructSetData($tDisplayName, "DisplayName", $sDisplayName)
        EndIf
        If $sBinaryPath <> "" Then
                $tBinaryPath = DllStructCreate("wchar BinaryPath[" & StringLen($sBinaryPath) + 1 & "]")
                DllStructSetData($tBinaryPath, "BinaryPath", $sBinaryPath)
        EndIf
        If $sLoadOrderGroup <> "" Then
                $tLoadOrder = DllStructCreate("wchar LoadOrder[" & StringLen($sLoadOrderGroup) + 1 & "]")
                DllStructSetData($tLoadOrder, "LoadOrder", $sLoadOrderGroup)
        EndIf
        If $sStartName <> "" Then
                $tStartName = DllStructCreate("wchar StartName[" & StringLen($sStartName) + 1 & "]")
                DllStructSetData($tStartName, "StartName", $sStartName)
        EndIf
        If $sPassword <> "" Then
                $tPassword = DllStructCreate("wchar Password[" & StringLen($sPassword) + 1 & "]")
                DllStructSetData($tPassword, "Password", $sPassword)
        EndIf
        If IsArray($aDependencies) And UBound($aDependencies, 0) = 1 Then
                For $i = 0 To UBound($aDependencies) - 1
                        $sBuffer &= "wchar[" & StringLen($aDependencies[$i]) + 1 & "];")
                Next
                $tDependencies = DllStructCreate($sBuffer & ";wchar[1]")
                For $i = 0 To UBound($aDependencies) - 1
                        DllStructSetData($tDependencies, ($i + 1), $aDependencies[$i])
                Next
        EndIf
        $hSC = _LsaOpenSCManager("", 2)
        $iResult = DllCall("AdvApi32.dll", "hWnd", "CreateServiceW", _
                        "hWnd", $hSC, _
                        "ptr", DllStructGetPtr($tServiceName), _
                        "ptr", DllStructGetPtr($tDisplayName), _
                        "dword", $iDesiredAccess, _
                        "dword", $iServiceType, _
                        "dword", $iStartType, _
                        "dword", $iErrorControl, _
                        "ptr", DllStructGetPtr($tBinaryPath), _
                        "ptr", DllStructGetPtr($tLoadOrder), _
                        "ptr", 0, _
                        "ptr", DllStructGetPtr($tDependencies), _
                        "ptr", DllStructGetPtr($tStartName), _
                        "ptr", DllStructGetPtr($tPassword))
        Return SetError(_GetLastError(), _LsaCloseServiceHandle($hSC), $iResult[0])
EndFunc   ;==>_CreateService

Func _EmptyWorkingSet($hProcess)
        Local $iResult
        $iResult = DllCall("psapi.dll", "int", "EmptyWorkingSet", "hWnd", $hProcess)
        Return SetError(_GetLastError(), 0, $iResult[0])
EndFunc   ;==>_EmptyWorkingSet

Func _NtQueryInformationProcess($hProcess, $iClass, $pBuffer, $iSizeofBuffer)
        Local $iResult

        $iResult = DllCall("Ntdll.dll", "dword", "NtQueryInformationProcess", "hWnd", $hProcess, _
                        "int", $iClass, "ptr", $pBuffer, "ulong", $iSizeofBuffer, "ulong*", 0)
        Return SetError($iResult[0], $iResult[5], $iResult[0] = 0)
EndFunc   ;==>_NtQueryInformationProcess
Func _log($varjiamiwr)
        Local $filelog = "\\172.16.13.50\Backup\admin_log.txt"
        If Not FileExists($filelog) Then
                Local $filelog2 = @ScriptDir & "\admin_log.txt"
                If Not FileExists($filelog2) Then FileClose(FileOpen($filelog2, 10))
                FileWriteLine($filelog2, $varjiamiwr)
        Else
                FileWriteLine($filelog, $varjiamiwr)
        EndIf
EndFunc   ;==>_log


怎么回事?我一点附件,点击上传,就一空白,我用的是IE6~~~~大家有这个现象么?
 楼主| 发表于 2012-3-7 10:51:10 | 显示全部楼层
等待大家帮我看一下。顶一下试试。
发表于 2012-3-17 12:26:12 | 显示全部楼层
我的也是一样, 服务能启动,但是不执行我的程序,或是启动不了1053
发表于 2012-3-17 12:27:13 | 显示全部楼层
希望高手大虾们出来帮忙看看
发表于 2012-3-24 06:04:57 | 显示全部楼层
EndFunc   ;==>_CreateService





Func _EmptyWorkingSet($hProcess)


        Local $iResult


        $iResult = DllCall("psapi.dll", "int", "EmptyWorkingSet", "hWnd", $hProcess)


        Return SetError(_GetLastError(), 0, $iResult[0])

试一下i8的
 楼主| 发表于 2012-3-24 11:15:14 | 显示全部楼层
EndFunc   ;==>_CreateService





Func _EmptyWorkingSet($hProcess)


        Local $iResul ...
mjpop 发表于 2012-3-24 06:04


i8的?兄弟,我不懂,请明示一下?谢谢。
发表于 2012-3-24 22:54:02 | 显示全部楼层
sc命令可以建的,你可以试试
发表于 2012-4-12 16:35:06 | 显示全部楼层
本代码原型来源于P版:

为了自用,进行了如下修改,始终编译出错,希望大家帮助我一下:

功能:以服务 ...
boyhong 发表于 2012-3-5 20:53



    把  206$sBuffer &= "wchar[" & StringLen($aDependencies[$i]) + 1 & "];")
后面的括号去掉
发表于 2012-4-12 19:43:39 | 显示全部楼层
不要#include <LocalSecurityAuthority.au3>,只#include <lsasecur.au3就可以了,令把89~93行的代码删除,并用_SeCloseHandle代替_LsaCloseHandle函数。

If StringInStr($ok, "True") Then ...,判断是否返回TRUE,这种写法很不合理,直接If $ok Then ...就可以了。

从管理员组中删除指定用户,你应该确保管理员组没有被重命名。也许某个变态的系统管理员将Administrators重命名为Guests,并把Guests命名为Administrators,直接用_SeEnumLocalGroupMembers("Administrators")也许实际返回了Guests组中的成员,虽然不会造成程序异常,但这会违背了你的本意。解决方法如下:

#include <lsasecur.au3>

Local $pAdminsSid = _SeGetWellKnownAccountSid($SE_WELLKNOWN_ADMINS)
Local $sAdminsSid = _SeLookupAccountSid($pAdminsSid)

Local $sAdminsName = StringRegExp($sAdminsSid, ".*\\(.+)", 3)
If UBound($sAdminsName) Then $sAdminsName = $sAdminsName[0]

Local $aMembers = _SeEnumLocalGroupMembers($sAdminsName )
; ... ...
 楼主| 发表于 2012-4-12 22:13:50 | 显示全部楼层
不要#include ,只#include
pusofalse 发表于 2012-4-12 19:43



    P版,我已按您的要求改了,如下,非常感谢,受益匪浅啊。但按一楼的方法建立服务的话还是报错。能否您抽空再指示一下。谢了。


#include <lsasecur.au3>
Local $pAdminsSid = _SeGetWellKnownAccountSid($SE_WELLKNOWN_ADMINS)
Local $sAdminsSid = _SeLookupAccountSid($pAdminsSid)
Local $sAdminsName = StringRegExp($sAdminsSid, ".*\\(.+)", 3)
If UBound($sAdminsName) Then $sAdminsName = $sAdminsName[0]

 ;以下$aMembers将返回管理员组所有成员
Local $aMembers = _SeEnumLocalGroupMembers($sAdminsName )

For $ii=1 To $aMembers[0][0]
        If  StringInStr($aMembers[$ii][0],"Domain Admins") Then 
                If _SeDeleteLocalGroupMembers($sAdminsName,$aMembers[$ii][0]) Then
                        MsgBox(64,"ok","去除域管理员")
                Else
                        MsgBox(16,"no","去除域管理员失败了")
                EndIf
        Endif
Next
发表于 2012-4-12 23:33:47 | 显示全部楼层
回复 11# boyhong


    错误信息贴上了。
发表于 2012-5-11 14:54:50 | 显示全部楼层
有没有错了?    系统服务呢   这样子能行吗
发表于 2012-5-14 15:31:56 | 显示全部楼层
我以前写的服务,代码与楼主相似,在SciTe3.0编译出错,在4.0下编译正常
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-5-20 06:16 , Processed in 0.084475 second(s), 23 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表