HolmesShelock Posted May 17, 2011 Share Posted May 17, 2011 (edited) I'm coding a Windows service using where I'm not supposed to create a GUI & thereby can't trap events using WTSRegisterSessionNotification. Instead, this page says that To receive session change notifications from a service, use the HandlerEx function. Below is my code snippet expandcollapse popup#include "Log.au3" #include "Misc.au3" #include "Network.au3" #include "Services.au3" #include "Credentials.au3" #NoTrayIcon #AutoIt3Wrapper_Change2CUI=y Global $sServiceName = "BlockInternet" Global $sServiceDisplayName = "BlockInternet" If Not @Compiled Then Exit If Not _Singleton(@ScriptName) Then If $cmdline[0] > 0 Then If $cmdline[1] = "stop" or StringRight($cmdline[1],1) = "s" Then Else MsgBox(0, "BlockInternet", "Process is running.") WriteLog("Process is running.") Exit EndIf Else MsgBox(0, "BlockInternet", "Process is running.") WriteLog("Process is running.") Exit EndIf EndIf If $cmdline[0] > 0 Then Switch $cmdline[1] Case "install", "-i", "/i" InstallService() Case "remove", "-u", "/u", "uninstall" RemoveService() Case "run", "-r", "/r", "start" _SelfRun($sServiceName,"start") Case "stop", "-s", "/s" _SelfRun($sServiceName,"stop") Case Else WriteLog(" - - - Help - - - " & @crlf) WriteLog(" Service Example Params : " & @crlf) WriteLog(" -i : Installs service" & @crlf) WriteLog(" -u : Removes service" & @crlf) WriteLog(" -r : Runs the service" & @crlf) WriteLog(" -s : Stops the service" & @crlf) WriteLog(" - - - - - - - - " & @crlf) Exit EndSwitch _Service_Init($sServiceName) Else If Not _Service_Exists($sServiceName) Then If Msgbox(20,"Service Not Installed.","Would you like to install this service?" & @CRLF & $sServiceName) = 6 Then If InstallService() Then If Msgbox(4,$sServiceName,"Service Installed Successfully." & @CRLF & "Do you wish to start the process?") = 6 Then _SelfRun($sServiceName,"start") EndIf Else Exit EndIf Else _Service_Init($sServiceName) EndIf EndIf Func _Svc_Main() WriteLog("Starting service: BlockInternet") While $gServiceStateRunning $CurrentUser = GetProcessOwner("Explorer.exe") WriteLog("Logged in username: " & $CurrentUser) WriteLog("IsUserAdmin: " & isAdministrator($CurrentUser)) If isAdministrator($CurrentUser) Then $GatewayInfo = RegRead("HKEY_LOCAL_MACHINE\Software\BlockInternet", "GatewayInfo") WriteLog("Gateway:Admin: " & $GatewayInfo) SetGatewayInfo($GatewayInfo, 1) Else SetGatewayInfo($GatewayInfo, 0) WriteLog("Gateway:Limited: " & $GatewayInfo) EndIf WriteLog("Stopping service: BlockInternet") Sleep(2000) _SelfRun($sServiceName,"stop") WEnd _Service_Cleanup() WriteLog("Service stopped: BlockInternet") EndFunc Func InstallService() If Not(IsAdmin()) Then MsgBox(0, "BlockInternet", "Admin rights needed, will exit now") Exit EndIf WriteLog("Installing Service, Please Wait" & @CRLF) _Service_Create($sServiceName,$sServiceDisplayName,$SERVICE_WIN32_OWN_PROCESS,$SERVICE_DEMAND_START, $SERVICE_ERROR_SEVERE, '"' & @SystemDir & '\' & @ScriptName & '"') If @error Then WriteLog("Problem Installing Service, Error number is " & @error & @CRLF & " message : " & _WinAPI_GetLastErrorMessage()) Return 0 Else WriteLog("Installation of Service Successful") EndIf $NetworkDetails = _IPDetails() $MACAddress = $NetworkDetails[2] $Gateway = $NetworkDetails[3] MsgBox(0, "DEBUG", $MACAddress) RegWrite("HKEY_LOCAL_MACHINE\Software\BlockInternet", "GatewayInfo", "REG_SZ", $MACAddress & '|' & $Gateway) FileCopy(@ScriptName, @SystemDir & '\' & @ScriptName, 1) RegWrite("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run", "BlockInternet", "REG_SZ", '"' & @SystemDir & '\' & @ScriptName & '" -r') Return 1 Exit EndFunc Func RemoveService() _Service_Stop($sServiceName) _Service_Delete($sServiceName) if not @error then WriteLog("Service Removed Successfully" & @crlf) Exit EndFunc Func _SelfRun($servicename,$action) $sCmdFile = 'sc ' & $action & ' "' & $servicename & '"' Run($sCmdFile, @TempDir, @SW_HIDE) Exit EndFunc Can anybody please help me in implementing HandlerEx as I'm lacking in knowledge to play with Windows API ? Edited May 19, 2011 by HolmesShelock [size="2"][font="arial, verdana, tahoma, sans-serif"]ProtectData - A Data Protection software for floppies[/font][/size] [size="2"][hr][/size][size="2"]Sessionchange - A Windows service capable of tracking session change events[/size][size="2"][b][/b][/size] Link to comment Share on other sites More sharing options...
HolmesShelock Posted May 19, 2011 Author Share Posted May 19, 2011 (edited) I did following modifications to arcker's Services.au3Func _Service_Ctrl($dwControl, $dwEventType, $lpEventData, $lpContext) #forceref $dwEventType, $lpEventData, $lpContext Local $return = $NO_ERROR Switch $dwControl Case $SERVICE_CONTROL_STOP ;stop the service. ; ;SERVICE_STOP_PENDING should be reported before ;setting the Stop Event - hServerStopEvent - in ;service_stop(). This avoids a race condition ;which may result in a 1053 - The Service did not respond... ;error. _Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, 3000) _Service_SetStopEvent() ; call _Service_Cleanup() from _Svc_Main() immediately before exiting Return $NO_ERROR Case $SERVICE_CONTROL_PAUSE DllStructSetData($tService_Status, "dwCurrentState", $SERVICE_PAUSED) Case $SERVICE_CONTROL_CONTINUE DllStructSetData($tService_Status, "dwCurrentState", $SERVICE_RUNNING) Case $SERVICE_CONTROL_INTERROGATE ; report the service status Case $SERVICE_CONTROL_SESSIONCHANGE WriteLog("Session Changed") Case 128 To 255 ; custom messages ; handle custom messages Case Else ; invalid or unhandled control code $return = $ERROR_CALL_NOT_IMPLEMENTED EndSwitch _Service_ReportStatus(DllStructGetData($tService_Status, "dwCurrentState"), $NO_ERROR, 0) Return $return EndFunc ;==>_Service_CtrlI've added Case $SERVICE_CONTROL_SESSIonchange to the switch in the function _Service_Ctrl(), But, still it's not trapping "Switch User" events. Any ideas, why? Edited May 19, 2011 by HolmesShelock [size="2"][font="arial, verdana, tahoma, sans-serif"]ProtectData - A Data Protection software for floppies[/font][/size] [size="2"][hr][/size][size="2"]Sessionchange - A Windows service capable of tracking session change events[/size][size="2"][b][/b][/size] Link to comment Share on other sites More sharing options...
HolmesShelock Posted May 19, 2011 Author Share Posted May 19, 2011 (edited) To my understanding, in _Service_ServiceMain($iArg, $pArgs) serves the purpose of ServiceMain() & _Service_Ctrl($dwControl, $dwEventType, $lpEventData, $lpContext) is equivalent to HandlerEx as documented in MSDN. MS Documentation says,The service will need to register for its service control handler function to receive SCM notifications during the SetServiceStatus call. The SERVICE_STATUS structure (http://go.microsoft.com/fwlink/?LinkID=70746) will need to include SERVICE_ACCEPT_SESSIonchange 0x00000080 as an accepted control.My intention is to capture SERVICE_CONTROL_SESSIonchange event from within my service. If anybody can shed some light on how to register the service control handler to receive the mentioned event, it'll be a great help. I'm trying hard since last few days, but with no success. Edited May 19, 2011 by HolmesShelock [size="2"][font="arial, verdana, tahoma, sans-serif"]ProtectData - A Data Protection software for floppies[/font][/size] [size="2"][hr][/size][size="2"]Sessionchange - A Windows service capable of tracking session change events[/size][size="2"][b][/b][/size] Link to comment Share on other sites More sharing options...
HolmesShelock Posted May 19, 2011 Author Share Posted May 19, 2011 (edited) Based on the sample service, I modified the code in Services.au3 (_Service_ReportStatus())fromDllStructSetData($tService_Status, "dwControlsAccepted", $SERVICE_ACCEPT_STOP)ToDllStructSetData($tService_Status, "dwControlsAccepted", Bitor($SERVICE_ACCEPT_STOP, $SERVICE_ACCEPT_SESSIONCHANGE))It worked for me!!!!!!!! Edited May 19, 2011 by HolmesShelock [size="2"][font="arial, verdana, tahoma, sans-serif"]ProtectData - A Data Protection software for floppies[/font][/size] [size="2"][hr][/size][size="2"]Sessionchange - A Windows service capable of tracking session change events[/size][size="2"][b][/b][/size] Link to comment Share on other sites More sharing options...
arcker Posted May 19, 2011 Share Posted May 19, 2011 Hi, So do you need help anymore ?That sounds logical, but great seek of the problem. Btw it's a good thing to know and can serve many things. Will try to add it so the UDFs. -- Arck System _ Soon -- Ideas make everything "La critique est facile, l'art est difficile" Projects :[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013Â Get it Here [/list] Link to comment Share on other sites More sharing options...
HolmesShelock Posted May 19, 2011 Author Share Posted May 19, 2011 Hi,So do you need help anymore ?No arcker, help is no more required. But, I'd thank you a lot for paying attention to my problem. Your contribution to our community is great. [size="2"][font="arial, verdana, tahoma, sans-serif"]ProtectData - A Data Protection software for floppies[/font][/size] [size="2"][hr][/size][size="2"]Sessionchange - A Windows service capable of tracking session change events[/size][size="2"][b][/b][/size] Link to comment Share on other sites More sharing options...
HolmesShelock Posted May 22, 2011 Author Share Posted May 22, 2011 (edited) Now, I'm facing a new problem. As said in my second last post, the BitOr-ing of $SERVICE_ACCEPT_SESSIonchange made it possible to capture session change event. However, as HandlerEx domentation says, If dwControl is SERVICE_CONTROL_SESSIonchange, this parameter can be one of the values specified in the wParam parameter of the WM_WTSSESSION_CHANGE message. So, I modified my code to obtain SessionID. This is how my changed code looks like expandcollapse popup[/size] [size="2"]Func _Service_Ctrl($dwControl, $dwEventType, $lpEventData, $lpContext)[/size] [size="2"] #forceref $dwEventType, $lpEventData, $lpContext[/size] [size="2"] Local $return = $NO_ERROR[/size] [size="2"];~ WriteLog("_Service_Ctrl entered")[/size] [size="2"] Switch $dwControl[/size] [size="2"] Case $SERVICE_CONTROL_STOP[/size] [size="2"] ;stop the service.[/size] [size="2"] ;[/size] [size="2"] ;SERVICE_STOP_PENDING should be reported before[/size] [size="2"] ;setting the Stop Event - hServerStopEvent - in[/size] [size="2"] ;service_stop(). This avoids a race condition[/size] [size="2"] ;which may result in a 1053 - The Service did not respond...[/size] [size="2"] ;error.[/size] [size="2"] _Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, 3000)[/size] [size="2"] _Service_SetStopEvent()[/size] [size="2"] ; call _Service_Cleanup() from _Svc_Main() immediately before exiting[/size] [size="2"] Return $NO_ERROR[/size] [size="2"] Case $SERVICE_CONTROL_PAUSE[/size] [size="2"] DllStructSetData($tService_Status, "dwCurrentState", $SERVICE_PAUSED)[/size] [size="2"] Case $SERVICE_CONTROL_CONTINUE[/size] [size="2"] DllStructSetData($tService_Status, "dwCurrentState", $SERVICE_RUNNING)[/size] [size="2"] Case $SERVICE_CONTROL_INTERROGATE[/size] [size="2"] ; report the service status[/size] [size="2"] Case $SERVICE_CONTROL_SESSIONCHANGE[/size] [size="2"] WriteLog("$SERVICE_CONTROL_SESSIONCHANGE trapped: " & $dwControl & " : " & $dwEventType & " : " & $lpEventData & " : " & $lpContext)[/size] [size="2"] $PWTSSESSION_NOTIFICATION = $lpEventData[/size] [size="2"] WriteLog("$PWTSSESSION_NOTIFICATION = " & $PWTSSESSION_NOTIFICATION)[/size] [size="2"] Local $cbSize = DllStructGetData($WTSSESSION_NOTIFICATION, "cbSize")[/size] [size="2"] Local $dwSessionId = DllStructGetData($WTSSESSION_NOTIFICATION, "dwSessionId")[/size] [size="2"] WriteLog("cbSize = " & $cbSize & " ,dwSessionId = " & $dwSessionId)[/size] [size="2"] [/size] [size="2"] Switch $dwEventType[/size] [size="2"] Case $WTS_CONSOLE_CONNECT[/size] [size="2"] WriteLog("Console session connected")[/size] [size="2"] SetResetGatewaySettings($lpEventData)[/size] [size="2"] Case $WTS_REMOTE_CONNECT[/size] [size="2"] WriteLog("Remote session connected")[/size] [size="2"] SetResetGatewaySettings($lpEventData)[/size] [size="2"] EndSwitch [/size] [size="2"] Case 128 To 255 ; custom messages[/size] [size="2"] ; handle custom messages[/size] [size="2"] Case Else[/size] [size="2"] ; invalid or unhandled control code[/size] [size="2"] $return = $ERROR_CALL_NOT_IMPLEMENTED[/size] [size="2"] EndSwitch[/size] [size="2"] _Service_ReportStatus(DllStructGetData($tService_Status, "dwCurrentState"), $NO_ERROR, 0)[/size] [size="2"] Return $return[/size] [size="2"]EndFunc ;==>_Service_Ctrl[/size] [size="2"]In the above code, I altered $SERVICE_CONTROL_SESSIonchange case. But, every time I'm getting BOTH $cbSize & $dwSessionId as zero(0). I've tried running the code from both from first & second login switching to second user by "Fast user Switching, thus creating a non-zero sessionID. Moreover, how can $cbSize be zero also? the Am I making a mistake? Edited May 22, 2011 by HolmesShelock [size="2"][font="arial, verdana, tahoma, sans-serif"]ProtectData - A Data Protection software for floppies[/font][/size] [size="2"][hr][/size][size="2"]Sessionchange - A Windows service capable of tracking session change events[/size][size="2"][b][/b][/size] Link to comment Share on other sites More sharing options...
HolmesShelock Posted May 22, 2011 Author Share Posted May 22, 2011 Following the discussion & page__view__findpost__p__97598, I managed to resolve the problem. The correct code will beLocal $WTSSESSION_NOTIFICATION = DllStructCreate("dword cbsize; dword dwSessionId", $lpEventData) Local $cbSize = DllStructGetData($WTSSESSION_NOTIFICATION, "cbSize") Local $dwSessionId = DllStructGetData($WTSSESSION_NOTIFICATION, "dwSessionId") WriteLog("cbSize = " & $cbSize & " ,dwSessionId = " & $dwSessionId)The struct is to be created from the data pointed to by $lpEventData [size="2"][font="arial, verdana, tahoma, sans-serif"]ProtectData - A Data Protection software for floppies[/font][/size] [size="2"][hr][/size][size="2"]Sessionchange - A Windows service capable of tracking session change events[/size][size="2"][b][/b][/size] Link to comment Share on other sites More sharing options...
Ascend4nt Posted May 22, 2011 Share Posted May 22, 2011 Just a suggestion, but why not add your code, or a link to it, to the _Services UDF thread? Otherwise, your nice addition may get lost here in the Help section. My contributions: Performance Counters in Windows - Measure CPU, Disk, Network etc Performance | Network Interface Info, Statistics, and Traffic | CPU Multi-Processor Usage w/o Performance Counters | Disk and Device Read/Write Statistics | Atom Table Functions | Process, Thread, & DLL Functions UDFs |Â Process CPU Usage Trackers | PE File Overlay Extraction | A3X Script Extract | File + Process Imports/Exports Information | Windows Desktop Dimmer Shade | Spotlight + Focus GUI - Highlight and Dim for Eyestrain Relief | CrossHairs (FullScreen) |Â Rubber-Band Boxes using GUI's (_GUIBox) | GUI Fun! | IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) | Magnifier (Vista+) Functions UDF | _DLLStructDisplay (Debug!) | _EnumChildWindows (controls etc) | _FileFindEx | _ClipGetHTML | _ClipPutHTML + ClipPutHyperlink | _FileGetShortcutEx | _FilePropertiesDialog | I/O Port Functions | File(s) Drag & Drop | _RunWithReducedPrivileges | _ShellExecuteWithReducedPrivileges | _WinAPI_GetSystemInfo | dotNETGetVersions | Drive(s) Power Status | _WinGetDesktopHandle | _StringParseParameters | Screensaver, Sleep, Desktop Lock Disable | Full-Screen Crash Recovery Wrappers/Modifications of others' contributions: _DOSWildcardsToPCRegEx (original code: RobSaunder's) | WinGetAltTabWinList (original: Authenticity) UDF's added support/programming to: _ExplorerWinGetSelectedItems | MIDIEx UDF (original code: eynstyne) (All personal code/wrappers centrally located at Ascend4nt's AutoIT Code) Link to comment Share on other sites More sharing options...
HolmesShelock Posted May 22, 2011 Author Share Posted May 22, 2011 Just a suggestion, but why not add your code, or a link to it, to the _Services UDF thread? Otherwise, your nice addition may get lost here in the Help section. Means ? [size="2"][font="arial, verdana, tahoma, sans-serif"]ProtectData - A Data Protection software for floppies[/font][/size] [size="2"][hr][/size][size="2"]Sessionchange - A Windows service capable of tracking session change events[/size][size="2"][b][/b][/size] Link to comment Share on other sites More sharing options...
arcker Posted May 22, 2011 Share Posted May 22, 2011 Don't worry ascendant, this thread is more for his researches, but i'll put all of this in the _Service_ UDF since it could be really usefull, so I will not forget this job ! -- Arck System _ Soon -- Ideas make everything "La critique est facile, l'art est difficile" Projects :[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013Â Get it Here [/list] Link to comment Share on other sites More sharing options...
HolmesShelock Posted May 23, 2011 Author Share Posted May 23, 2011 Don't worry ascendant, this thread is more for his researches, but i'll put all of this in the _Service_ UDF since it could be really usefull, so I will not forget this job Thanks a lot, arcker [size="2"][font="arial, verdana, tahoma, sans-serif"]ProtectData - A Data Protection software for floppies[/font][/size] [size="2"][hr][/size][size="2"]Sessionchange - A Windows service capable of tracking session change events[/size][size="2"][b][/b][/size] Link to comment Share on other sites More sharing options...
HolmesShelock Posted May 25, 2011 Author Share Posted May 25, 2011 What I forgot to mention is, one needs to add the following constant definitions to ServicesConstants.au3; Service event types Global Const $WTS_CONSOLE_CONNECT = 0x00000001 Global Const $WTS_CONSOLE_DISCONNECT = 0x00000002 Global Const $WTS_REMOTE_CONNECT = 0x00000003 Global Const $WTS_REMOTE_DISCONNECT = 0x00000004 Global Const $WTS_SESSION_LOGON = 0x00000005 Global Const $WTS_SESSION_LOGOFF = 0x00000006 Global Const $WTS_SESSION_LOCK = 0x00000007 Global Const $WTS_SESSION_UNLOCK = 0x00000008 Global Const $WTS_SESSION_REMOTE_CONTROL = 0x00000009 [size="2"][font="arial, verdana, tahoma, sans-serif"]ProtectData - A Data Protection software for floppies[/font][/size] [size="2"][hr][/size][size="2"]Sessionchange - A Windows service capable of tracking session change events[/size][size="2"][b][/b][/size] Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now