有关P版的服务程序与桌面交互后,会导致win7之前的系统桌面卡死1分钟左右
本帖最后由 txm888 于 2014-5-16 08:50 编辑有关P版的服务程序与桌面交互启动后,会导致win7之前的系统(如:winxp,win2003,win2000)桌面卡死1分钟左右。
如果将HKLM\SYSTEM\CurrentControlSet\Control\Windows\的值改为1,禁用桌面交互,再启动服务,就不会卡
或者将源码中的交互参数$SERVICE_INTERACTIVE_PROCESS去掉,也不会导致卡。
卡死的过程是这样,比如,先结束explorer.exe,再结束本服务进程(服务进程自动重新运行),然后再新建explorer.exe,这时桌面是出不来的,必须再次结束本服务进程,桌面才能跳出来,而且,这时又立即打开控制面板项,也打不开,至少要等1分多钟才能打开
由于本服务程序含有窗口操作的函数,必需要用到桌面交互选项
不知道有哪位前辈也遇到过这问题,还请帮指点下,谢谢#NoTrayIcon
#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 = "Au3MemCleaner"
; 判断此服务程序是否由SCM启动。
Local $tProcessBasic = DllStructCreate("dword;ptr;ulong_ptr;ulong")
_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")
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 = [[$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
$aProcess = ProcessList()
For $i = 1 To $aProcess
$hProcess = _OpenProcess($aProcess[$i])
_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)
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)
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)
EndFunc ;==>_RegisterServiceCtrlHandlerEx
Func _StartServiceCtrlDispatcher($pServiceTable)
Local $iResult
$iResult = DllCall("AdvApi32.dll", "int", "StartServiceCtrlDispatcher", _
"ptr", $pServiceTable)
Return SetError(_GetLastError(), 0, $iResult)
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")
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)
EndFunc ;==>_CreateService
Func _EmptyWorkingSet($hProcess)
Local $iResult
$iResult = DllCall("psapi.dll", "int", "EmptyWorkingSet", "hWnd", $hProcess)
Return SetError(_GetLastError(), 0, $iResult)
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, $iResult, $iResult = 0)
EndFunc ;==>_NtQueryInformationProcess原贴地址:http://www.autoitx.com/thread-18059-1-1.html http://www.autoitx.com/forum.php?mod=viewthread&tid=15472&highlight=%B1%A3%BB%A4 看看这个..... 回复 2# zjw201314
谢谢,目标贴的代码也测试了,仍然存在卡死一分钟左右的问题,不知道是哪里的问题 P版快来啊,请教这问题{:face (394):} 回复 2# zjw201314
通过这段时间以来,对P版服务程序关注,尝试着安装系统(原版xp和不同类型的GHOST版xp),在 zjw201314 坛友的启发下,发现用360打完补丁,就解决了桌面卡的问题(服务程序刚启动,任务栏无法显示,要等1分多钟),最后细细研究360打补丁,反复研究补丁,一批一批过滤打,人工打,都不行,最好猜问题怎么了?原来是360打补丁的同时,将我的默认浏览器改成IE了,后来人工将默认浏览器改成IE,发现果真是这问题,然后将网上的各种浏览器下载下来研究,看哪些浏览器设计为默认值会发生卡的问题,发现除了IE、百度浏览器、火狐浏览器、2345智能浏览器外的浏览器,都存在这问题(包含:世界之窗、世界之窗极速版、谷歌浏览器、猎豹浏览器、Opera、搜狗高速浏览器、360安全浏览器、闪游浏览器),还好算解决了卡的问题,在此做一个记录,方便有遇到这问题的朋友第一时间得到解决。
还是Skyfree老大的那句话,程序BUG,永远从自身查起,因为开发者时间是有限的,而我们在受益的同时,也应该同时积极测试,并反馈问题,以方便后来人。
但这不久,又发现另一问题,虽然桌面不卡了,但是如果才启动服务程序,立即去打开控制面板,发现任务栏,控制面板会卡住2分钟左右,此时打开我的电脑,及桌面上的操作仍然可以继续,后来有一朋友也是看了此贴联系到我,说我问题解决了没,说他用C语言写了个服务程序,用于监视别的程序运行状态,桌面不卡,也是刚启动服务导致控制面板卡死,后来他联系他朋友,仔细分析,发现是少了什么应答的语句,最终解决了问题,我现在将他们的聊天记录发上来,希望有兴趣的朋友看下,对照看是哪里出的问题,好及时纠正,我也想Au3写的服务程序很好用。
本人文化水平不高,上述语句有点乱,还请阅读者见谅!
页:
[1]