本帖最后由 給点阳光 于 2012-5-26 09:52 编辑
服务程序不像普通的用户程序,服务程序需要遵循特定的服务规则。就像用SC命令将Notepad.exe注册为服务再开启一样,会返回“服务没有及时响应(1503)”的错误。
下面的代码没有调用任何第三方,纯AU3实现。以下只是演示了一个合法服务程序的编写,代码不具备任何功能。先编译为exe,再用SC命令将此注册为服务,服务名称用AutoIt3Service,否则下面的代码没有任何意义。用services.msc或sc.exe执行开启、停止等操作,会发现这果真是一个合法服务程序。
#Region ;**** 参数创建于 ACNWrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#EndRegion ;**** 参数创建于 ACNWrapper_GUI ****
Const $hAdvApi32Dll = DllOpen("AdvApi32.dll")
Const $hKernel32Dll = DllOpen("Kernel32.dll")
Const $tagSERVICE_TABLE_ENTRY = "ptr ServiceName;ptr ServiceMain"
Const $tagSERVICE_STATUS = "dword ServiceType;dword CurrentState;dword ControlsAccepted;dword Win32ExitCode;dword ServiceSpecificExitCode;dword CheckPoint;dword WaitHint"
Global $hServiceStatus, $tServiceStatus, $pServiceStatus
Global $hServiceMain, $pServiceMain, $tServiceTable, $pServiceTable
Global $hServiceHandlerEx, $pServiceHandlerEx
$hServiceMain = DllCallbackRegister("_ServiceMain", "none", "dword;ptr")
$pServiceMain = DllCallbackGetPtr($hServiceMain)
$hServiceHandlerEx = DllCallbackRegister("_ServiceHandlerEx", "dword", "dword;dword;ptr;ptr")
$pServiceHandlerEx = DllCallbackGetPtr($hServiceHandlerEx)
$pServiceTable = _ServiceHeapAlloc(32)
$tServiceTable = DllStructCreate($tagSERVICE_TABLE_ENTRY, $pServiceTable)
DllStructSetData($tServiceTable, "ServiceName", $pServiceTable + 16)
DllStructSetData($tServiceTable, "ServiceMain", $pServiceMain)
$tServiceName = DllStructCreate("char ServiceName[16]", $pServiceTable + 16)
DllStructSetData($tServiceName, "ServiceName", "AutoIt3Service")
$tServiceStatus = DllStructCreate($tagSERVICE_STATUS)
$pServiceStatus = DllStructGetPtr($tServiceStatus)
DllStructSetData($tServiceStatus, "ServiceType", 16)
DllStructSetData($tServiceStatus, "ControlsAccepted", 3)
_StartServiceCtrlDispatcher($pServiceTable)
Func _StartServiceCtrlDispatcher($pServiceTable)
Local $iResult
$iResult = DllCall($hAdvApi32Dll, "int", "StartServiceCtrlDispatcher", "ptr", $pServiceTable)
Return SetError(_ServiceLastError(), 0, $iResult[0])
EndFunc ;==>_StartServiceCtrlDispatcher
Func _SetServiceStatus($hServiceStatus, $pServiceStatus)
Local $iResult
$iResult = DllCall($hAdvApi32Dll, "int", "SetServiceStatus", "hWnd", $hServiceStatus, _
"ptr", $pServiceStatus)
Return SetError(_ServiceLastError(), 0, $iResult[0])
EndFunc ;==>_SerServiceStatus
Func _RegisterServiceCtrlHandlerEx($sServiceName, $pHandlerEx, $pContext = 0)
Local $iResult
$iResult = DllCall($hAdvApi32Dll, "hWnd", "RegisterServiceCtrlHandlerEx", _
"str", $sServiceName, "ptr", $pHandlerEx, "ptr", $pContext)
Return SetError(_ServiceLastError(), 0, $iResult[0])
EndFunc ;==>_RegisterServiceCtrlHandlerEx
Func _ServiceHandlerEx($iRequest, $iEventType, $pEventData, $pContext)
Switch $iRequest
Case 1
DllStructSetData($tServiceStatus, "CurrentState", 1)
_SetServiceStatus($hServiceStatus, $pServiceStatus)
Return 0
Case 2
DllStructSetData($tServiceStatus, "CurrentState", 7)
_SetServiceStatus($hServiceStatus, $pServiceStatus)
Return 0
Case 3
DllStructSetData($tServiceStatus, "CurrentState", 5)
_SetServiceStatus($hServiceStatus, $pServiceStatus)
Sleep(5000)
DllStructSetData($tServiceStatus, "CurrentState", 4)
_SetServiceStatus($hServiceStatus, $pServiceStatus)
Return 0
Case 4
_SetServiceStatus($hServiceStatus, $pServiceStatus)
Return 0
EndSwitch
EndFunc ;==>_ServiceHandlerEx
Func _ServiceHeapAlloc($iSize, $iFlags = 8)
If $iSize < 1 Then Return SetError(87, 0, 0)
Local $hHeap, $iResult
$hHeap = DllCall($hKernel32Dll, "hWnd", "GetProcessHeap")
$iResult = DllCall($hKernel32Dll, "ptr", "HeapAlloc", "hWnd", $hHeap[0], _
"dword", $iFlags, "dword", $iSize)
Return $iResult[0]
EndFunc ;==>_ServiceHeapAlloc
Func _ServiceHeapFree(ByRef $pBuffer)
If $pBuffer = 0 Then Return SetError(87, 0, 0)
Local $iResult, $hHeap
$hHeap = DllCall($hKernel32Dll, "hWnd", "GetProcessHeap")
$iResult = DllCall($hKernel32Dll, "int", "HeapFree", "hWnd", $hHeap[0], _
"dword", 0, "ptr", $pBuffer)
If $iResult[0] Then $pBuffer = 0
Return $iResult[0]
EndFunc ;==>_ServiceHeapFree
Func _ServiceHeapSize(ByRef $pBuffer)
If $pBuffer = 0 Then Return SetError(87, 0, 0)
Local $iResult, $hHeap
$hHeap = DllCall($hKernel32Dll, "hWnd", "GetProcessHeap")
$iResult = DllCall($hKernel32Dll, "int", "HeapSize", "hWnd", $hHeap[0], _
"dword", 0, "ptr", $pBuffer)
Return $iResult[0]
EndFunc ;==>_ServiceHeapFree
Func _ServiceLastError()
Local $iResult
$iResult = DllCall($hKernel32Dll, "dword", "GetLastError")
Return $iResult[0]
EndFunc ;==>_ServiceLastError
Func _ServiceMain($iNumberofArgs, $pArgs)
$hServiceStatus = _RegisterServiceCtrlHandlerEx("AutoIt3Service", $pServiceHandlerEx)
DllStructSetData($tServiceStatus, "CurrentState", 4)
_SetServiceStatus($hServiceStatus, $pServiceStatus)
EndFunc ;==>_ServiceMain
原来论坛已有人提过这样的问题,http://www.autoitx.com/forum.php ... E%CE%F1%B3%CC%D0%F2 |