Jump to content

RegisterWaitForSingleObject for handling events with callback

Recommended Posts

Hey everyone,

I searched some hours for a way to use the function WaitForSingleObject not as a function the script has to wait for, but a function which calls a callback function when the event is signaled. I found a way with RegisterWaitForSingleObject  but no AutoIt implemention, so I made one on my own, and now I want to share it with you guys!

The only limitation by this implemention is that you are not able to use more than one callback at once. to avoid this, you could write a static array in the function which fills with the selfmade callback structs. If you find another way, let me know!


#include <WinAPI.au3>
#include 'RegisterWaitForSingleObject.au3'

Global $fExit = False

Local $hPid = Run("notepad.exe")
Local $hProcess = _WinAPI_OpenProcess(0x00100000, False, $hPid) ; SYNCHRONIZE (0x00100000)
ControlSetText(WinWait("[CLASS:Notepad]"), "", "[CLASS:Edit; INSTANCE:1]", "Close Editor or wait 3 seconds for timeout")

;Registers the _TestFunc with a timeout of 3 secs.
;The _TestFunc shall be like this: _TestFunc($fTimeout)
;where $fTimeout signalise wether timeout reached (True) or event is in signaled state (False)
_WinAPI_RegisterWaitForSingleObject($hProcess, "_TestFunc", 3000)

While Not $fExit
    ConsoleWrite("Do some stuff at " & @HOUR & ":" & @MIN & ":" & @SEC & "." & @MSEC & @CRLF)

ConsoleWrite("Bye" & @CRLF)

Func _TestFunc($fTimeout)
    If $fTimeout Then
        ConsoleWrite("Timeout reached" & @CRLF)

        ConsoleWrite("Object is in signaled state" & @CRLF)
    $fExit = True
EndFunc   ;==>_TestFunc

Hope you like it and find use for it!




www.AutoIt.de - Moderator of the German AutoIt Forum


Link to post
Share on other sites
  • Moderators

Am I missing it, or do you never free the DllCallbackRegister?

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to post
Share on other sites

Am I missing it, or do you never free the DllCallbackRegister?


Yup, you're rigth. But I initalize it as a static variable; therefore it's only initalized one time, the same Callback for all functions (the Handler function never changes so there is no need to initalize DllCallbackRegister every time)



www.AutoIt.de - Moderator of the German AutoIt Forum


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Jefrey
      Hi guys/girls!
      I'm gonna share this UDF I made today.
      It allows you to easily create TCP servers and set actions depending on three events: OnConnect, OnDisconnect and OnReceive.
      It is also multi client (you can set the clients limit) and you can also bind a Console-based executable to the socket (similar to -e parameter in NetCat). This feature is useful if you want to use some Console UDF to create your TCP server and don't want to mix it with the TCP functions. Also, as it runs on background just firing events, it won't pause your script while listening/receiving, so you can do anything else (stop and restart the server, allow the user to click buttons or just wait on an infinite loop) that your callbacks will be called once the event is fired.
      It's also very easy to use. See this examples:
      Example #1: A basic server
      By running this (then connecting to the server using Netcat), you will receive a message box telling you when some user connects or disconnects (the socket ID and his IP address is passed as parameter to your callback function) and also when the user sends something over the TCP socket (the data sent is passed as parameter).
      #cs Download netcat at https://eternallybored.org/misc/netcat/ Execute this script Run in CMD: nc -vv 8081 #ce #include "TCPServer.au3" ; First we set the callback functions for the three events (none of them is mandatory) _TCPServer_OnConnect("connected") _TCPServer_OnDisconnect("disconnect") _TCPServer_OnReceive("received") ; And some parameters _TCPServer_DebugMode(True) _TCPServer_SetMaxClients(10) ; Finally we start the server at port 8081 at any interface _TCPServer_Start(8081) Func connected($iSocket, $sIP) MsgBox(0, "Client connected", "Client " & $sIP & " connected!") _TCPServer_Broadcast('new client connected guys', $iSocket) _TCPServer_Send($iSocket, "Hey! Write something ;)" & @CRLF) _TCPServer_SetParam($iSocket, "will write") EndFunc ;==>connected Func disconnect($iSocket, $sIP) MsgBox(0, "Client disconnected", "Client " & $sIP & " disconnected from socket " & $iSocket) EndFunc ;==>disconnect Func received($iSocket, $sIP, $sData, $sPar) MsgBox(0, "Data received from " & $sIP, $sData & @CRLF & "Parameter: " & $sPar) _TCPServer_Send($iSocket, "You wrote: " & $sData) _TCPServer_SetParam($iSocket, 'will write again') EndFunc ;==>received While 1 Sleep(100) WEnd Example #2: A basic HTTP server (just one page, as it is just an example)
      In this example, we run this code and point our browser to the address mentioned on the comments. A basic "It works!" page is show.
      #cs Run this script Point your browser to http://localhost:8081/ #ce #include "TCPServer.au3" _TCPServer_OnReceive("received") _TCPServer_DebugMode(True) _TCPServer_SetMaxClients(10) _TCPServer_Start(8081) Func received($iSocket, $sIP, $sData, $sParam) _TCPServer_Send($iSocket, "HTTP/1.0 200 OK" & @CRLF & _ "Content-Type: text/html" & @CRLF & @CRLF & _ "<h1>It works!</h1>" & @CRLF & _ "<p>This is the default web page for this server.</p>" & @CRLF & _ "<p>However this server is just a 26-lines example.</p>") _TCPServer_Close($iSocket) EndFunc ;==>received While 1 Sleep(100) WEnd Example #3: A telnet-like server (Command Prompt bound to the socket after password requesting)
      By running this example and connecting with Netcat, we will be asked for a password, which is 12345 as we set on the script. If the password is correct, we will see the Command Prompt live-updated (try running a ping to some server, for example).
      #cs Download netcat at https://eternallybored.org/misc/netcat/ Execute this script Run in CMD: nc -vv 8081 #ce #include "TCPServer.au3" Global $sPassword = "12345" ; input server password here _TCPServer_OnConnect("connected") _TCPServer_OnDisconnect("disconnect") _TCPServer_OnReceive("received") _TCPServer_DebugMode(True) _TCPServer_SetMaxClients(10) _TCPServer_Start(8081) Func connected($iSocket, $sIP) _TCPServer_Send($iSocket, "Welcome! Please input password: ") _TCPServer_SetParam($iSocket, 'login') EndFunc ;==>connected Func disconnect($iSocket, $sIP) MsgBox(0, "Client disconnected", "Client " & $sIP & " disconnected from socket " & $iSocket) EndFunc ;==>disconnect Func received($iSocket, $sIP, $sData, $sParam) If $sParam = "login" Then If $sData <> $sPassword Then _TCPServer_Send($iSocket, "Wrong password. Try again: ") Return Else _TCPServer_SetParam($iSocket, 'command') _TCPServer_BindAppToSocket($iSocket, 'cmd.exe') EndIf ElseIf $sParam = "command" Then _TCPServer_SendToBound($iSocket, $sData) EndIf EndFunc ;==>received While 1 Sleep(100) WEnd The limit is your imagination? Well, no sure. We have this limit:
      You can't create more than one server with this UDF in the same script. However, you can pause and resume (read 'stop and start again') your server at any time in your script, without having to reset the server settings. And of course you can have many clients (or just one, it's your choice!) in the same server. Or run multiple instances. Functions list:
      Help file and more examples included!
      Latest version:
      Download: TCPServer UDF.rar
      1.0 - First release - 18/04/2015 - Bug fix __TCPServer_Accept internal function / help file recompiled - 26/04/2015 Perhaps you will need to uncompress the file first, so the help file will work.
      Fork this on Github: http://github.com/jesobreira/TCPServerUDF
      TCPServer UDF.rar
    • By revonatu
      I have a quite complex script and now I would like to define the initial parameters and directories via a GUI.
      The first question is: Which GUI mode is best for my purposes? I don't understand in detail what the difference is. I tend to OnEvent mode as I only need the GUI at the beginning.
      Edit: Ok, only in loop mode the file selection works. One question solved. But how do I pause my script and start it after I am done with the GUI?
      This is my code so far:
      #include <MsgBoxConstants.au3> #include <WindowsConstants.au3> #include <File.au3> #include <FileConstants.au3> #include <StringConstants.au3> #include <Date.au3> #include <Array.au3> #include <GUIConstantsEx.au3> Local $AutoIt_GUI = GUICreate("ATCOR4 - Initial Settings", 500, 400) ; title, width and height Local $idLabel0 = GUICtrlCreateLabel("Wellcome to this ATCOR4 automation. Please choose your preferences.", 30, 10) ; text and position (left, top) Local $idButton1 = GUICtrlCreateButton("*.meta file", 30, 50, 60) Local $idLabel1 = GUICtrlCreateLabel("select the meta file with start and end time", 120, 55, 300, 60) Local $idButton2 = GUICtrlCreateButton("*.pos file", 30, 80, 60); name, position and width Local $idLabel2 = GUICtrlCreateLabel("select the pos file with flight geometry", 120, 85, 300, 60) Local $idCombo1 = GUICtrlCreateCombo("Operation Type", 30, 150, 100) GUICtrlSetData($idCombo1, "GUI|.inn file", "Operation Type") Global $OperationMode = '"' & GUICtrlRead($idCombo1) & '"' GUISetState(@SW_SHOW) ; display this GUI Local $idMsg = 0 ; In this message loop we use variables to keep track of changes to the GUI controls While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Exit ;Case $GUI_EVENT_MINIMIZE ;MsgBox($MB_SYSTEMMODAL, "", "Dialog minimized", 2) ;Case $GUI_EVENT_MAXIMIZE ;MsgBox($MB_SYSTEMMODAL, "", "Dialog restored", 2) Case $idButton1 Local $MetaOpenDialog = FileOpenDialog("Select the meta file...", @ScriptDir & "\", "Meta (*.meta)") $metaPath = $MetaOpenDialog GUICtrlSetData($idLabel1, $MetaOpenDialog) Case $idButton2 Local $PosOpenDialog = FileOpenDialog("Select the pos file...", @ScriptDir & "\", "Pos (*.pos)") $posPath = $PosOpenDialog GUICtrlSetData($idLabel2, $PosOpenDialog) EndSwitch WEnd Thanks in advance for any hints and suggestions (the shorter the code the better).
    • By MikahS
      Hello all,
      Back again it seems. I've hit a snag in the below script. I use this on win 7 and XP machines frequently and have just realized that sorting using column headers is not 'working' (is not updating listview; it looks like something is going on behind the scenes..) when clicked. Also this does not show the sorting arrow when using the callback sort functionality.
      So, to sum up, I am not seeing the arrow keys when clicking the column header to sort. And, it is not sorting the values in the $List1 ListView box on a win XP machine.
      #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <EditConstants.au3> #include <Constants.au3> #include <GUIListBox.au3> #include <GUIEdit.au3> #include <GuiListView.au3> #include <Array.au3> #include <ButtonConstants.au3> #include <ScrollBarConstants.au3> #include <GuiScrollBars.au3> Local $List1, $List2, $List3, $List4, $GUIhandle Local $Button19, $Button91, $ButtonAZ, $ButtonZA Local $hChild_1, $cLabel_1, $cLabel_2, $cLabel_3 GUI() Repaint() Local $bSysMsg = False Local $aRect = _GUICtrlListView_GetItemRect($List1, 0) $iDeltaY = $aRect[3] - $aRect[1] _GUIScrollBars_EnableScrollBar(ControlGetHandle("", "", $List2), $SB_BOTH, $ESB_DISABLE_BOTH) _GUIScrollBars_EnableScrollBar(ControlGetHandle("", "", $List3), $SB_BOTH, $ESB_DISABLE_BOTH) _GUICtrlListView_RegisterSortCallBack($List1) _GUICtrlListView_RegisterSortCallBack($List2) _GUICtrlListView_RegisterSortCallBack($List3) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUIRegisterMsg($WM_SIZE, "WM_SIZE") GUIRegisterMsg($WM_SYSCOMMAND, "_WM_SYSCOMMAND") While 1     $msg = GUIGetMsg(1)     Switch $msg[1]         Case $GUIhandle             Switch $msg[0]                 Case $GUI_EVENT_CLOSE                     Quit()             EndSwitch             If $bSysMsg Then                 $bSysMsg = False                 _Resize_ListViews()             EndIf         Case $hChild_1             Switch $msg[0]                 Case $GUI_EVENT_CLOSE                     GUIDelete($hChild_1)             EndSwitch     EndSwitch WEnd Func Repaint()     Local $L1, $L2, $L3     _GUICtrlListView_BeginUpdate($List1)     _GUICtrlListView_DeleteAllItems($List1)     _GUICtrlListView_BeginUpdate($List2)     _GUICtrlListView_DeleteAllItems($List2)     _GUICtrlListView_BeginUpdate($List3)     _GUICtrlListView_DeleteAllItems($List3)     For $Index = 0 To 10 Step 1         $L1 = _GUICtrlListView_AddItem($List1, $Index, $Index)         $L2 = _GUICtrlListView_AddItem($List2, $Index, $Index)         $L3 = _GUICtrlListView_AddItem($List3, $Index, $Index)     Next     _GUICtrlListView_SetColumnWidth($List1, 0, $LVSCW_AUTOSIZE)     _GUICtrlListView_SetColumnWidth($List2, 0, $LVSCW_AUTOSIZE)     _GUICtrlListView_EndUpdate($List1)     _GUICtrlListView_EndUpdate($List2)     _GUICtrlListView_EndUpdate($List3) EndFunc   ;==>Repaint Func Quit()     _GUICtrlListView_UnRegisterSortCallBack($List1)     _GUICtrlListView_UnRegisterSortCallBack($List2)     _GUICtrlListView_UnRegisterSortCallBack($List3)     Exit EndFunc   ;==>Quit Func GUI()     Local $Index, $LV1, $LV2, $LV3, $L1_EX, $L2_EX, $L3_EX     $GUIhandle = GUICreate("ArchServer", 680, 575, -1, -1, $WS_SIZEBOX + $WS_SYSMENU + $WS_MAXIMIZEBOX + $WS_MINIMIZEBOX) ;creates the parent window     $List1 = _GUICtrlListView_Create($GUIhandle, "Computer Name ", 20, 35, 300, 448, -1, $LVS_EX_DOUBLEBUFFER) ;;$ES_READONLY incase you don't want to be able to select text     $cLabel_1 = GUICtrlCreateLabel("", 20, 35, 300, 448)     GUICtrlSetState($cLabel_1, $GUI_DISABLE)     GUICtrlSetResizing($cLabel_1, $GUI_DOCKAUTO)     GUICtrlSetBkColor($cLabel_1, $GUI_BKCOLOR_TRANSPARENT)     _GUICtrlListView_SetExtendedListViewStyle($List1, $LVS_EX_TWOCLICKACTIVATE)     $List2 = _GUICtrlListView_Create($GUIhandle, "Date/Time", 355, 35, 190, 450, -1, BitOR($LVS_EX_DOUBLEBUFFER, $LVS_EX_FLATSB))     $cLabel_2 = GUICtrlCreateLabel("", 355, 35, 190, 450)     GUICtrlSetState($cLabel_2, $GUI_DISABLE)     GUICtrlSetResizing($cLabel_2, $GUI_DOCKAUTO)     GUICtrlSetBkColor($cLabel_2, $GUI_BKCOLOR_TRANSPARENT)     $List3 = _GUICtrlListView_Create($GUIhandle, "Speed", 574, 35, 95, 450, -1, BitOR($LVS_EX_DOUBLEBUFFER, $LVS_EX_FLATSB))     $cLabel_3 = GUICtrlCreateLabel("", 574, 35, 95, 450)     GUICtrlSetState($cLabel_3, $GUI_DISABLE)     GUICtrlSetResizing($cLabel_3, $GUI_DOCKAUTO)     GUICtrlSetBkColor($cLabel_3, $GUI_BKCOLOR_TRANSPARENT)     GUICtrlCreateLabel("Additional Info", 20, 489) ;creates the label for $List4     GUICtrlSetResizing(-1, $GUI_DOCKSIZE)     $List4 = GUICtrlCreateList("", 20, 512, 635, 40, BitOR($WS_BORDER, $WS_VSCROLL), $ES_READONLY)     GUICtrlSetResizing($List4, $GUI_DOCKAUTO)     GUICtrlCreateLabel("Active Connections: ", 525, 487) ;creates the label for the active connections     GUICtrlSetResizing(-1, $GUI_DOCKSIZE)     $ActiveConnections = GUICtrlCreateList("0", 625, 486, 30, 30) ;dynamically updating list of connections as they come in     GUICtrlSetResizing($ActiveConnections, $GUI_DOCKSIZE)     GUICtrlSetResizing(-1, $GUI_DOCKSIZE)     GUISetState(@SW_SHOW) ;shows the GUI window     For $Index = 0 To 10 Step 1         $LV1 = _GUICtrlListView_AddItem($List1, " ") ;adds a default value into $List1         $LV2 = _GUICtrlListView_AddItem($List2, " ") ;adds a default value into $List2         $LV3 = _GUICtrlListView_AddItem($List3, " ") ;adds a default value into $List3     Next EndFunc   ;==>GUI Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)     Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, _             $ceLines, $cl     $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)     $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))     $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")     $iCode = DllStructGetData($tNMHDR, "Code")     Local Const $iLines = _SendMessage($List1, $LVM_GETTOPINDEX) - _SendMessage($List2, $LVM_GETTOPINDEX)     _SendMessage($List2, $LVM_SCROLL, 0, $iLines * $iDeltaY)     _SendMessage($List3, $LVM_SCROLL, 0, $iLines * $iDeltaY)     Switch $hWndFrom         Case $List1             Switch $iCode                 Case $LVN_COLUMNCLICK                     _GUICtrlListView_SortItems($List1, GUICtrlGetState($List1))                 Case $NM_CLICK                     $sData = _GUICtrlListView_GetSelectedIndices($List1)                     _GUICtrlListView_SetItemSelected($List2, $sData, True, False)                     _GUICtrlListView_SetItemSelected($List3, $sData, True, False)             EndSwitch         Case $List2             Switch $iCode                 Case $LVN_COLUMNCLICK                     _GUICtrlListView_SortItems($List1, GUICtrlGetState($List1))                 Case $NM_CLICK                     $sData = _GUICtrlListView_GetSelectedIndices($List2)                     _GUICtrlListView_SetItemSelected($List1, $sData, True, False)                     _GUICtrlListView_SetItemSelected($List3, $sData, True, False)             EndSwitch         Case $List3             Switch $iCode                 Case $LVN_COLUMNCLICK                     _GUICtrlListView_SortItems($List1, GUICtrlGetState($List1))                 Case $NM_CLICK                     $sData = _GUICtrlListView_GetSelectedIndices($List3)                     _GUICtrlListView_SetItemSelected($List1, $sData, True, False)                     _GUICtrlListView_SetItemSelected($List2, $sData, True, False)             EndSwitch     EndSwitch EndFunc   ;==>WM_NOTIFY Func WM_SIZE($hWnd, $msg, $wParam, $lParam)     _Resize_ListViews()     Return $GUI_RUNDEFMSG EndFunc   ;==>WM_SIZE Func _WM_SYSCOMMAND($hWnd, $msg, $wParam, $lParam)     Const $SC_MAXIMIZE = 0xF030     Const $SC_RESTORE = 0xF120     Switch $wParam         Case $SC_MAXIMIZE, $SC_RESTORE             $bSysMsg = True     EndSwitch EndFunc   ;==>_WM_SYSCOMMAND Func _Resize_ListViews()     $aRet = ControlGetPos($GUIhandle, "", $cLabel_1)     WinMove($List1, "", $aRet[0], $aRet[1], $aRet[2], $aRet[3])     $aRet = ControlGetPos($GUIhandle, "", $cLabel_2)     WinMove($List2, "", $aRet[0], $aRet[1], $aRet[2], $aRet[3])     $aRet = ControlGetPos($GUIhandle, "", $cLabel_3)     WinMove($List3, "", $aRet[0], $aRet[1], $aRet[2], $aRet[3]) EndFunc   ;==>_Resize_ListViews ;========RESIZE FUNCTIONALITY THANKS TO MELBA All replies are much appreciated!
    • By GtaSpider
      Hey folks,
      I just explored the new helpfile and found a new Keyword (dunno if its that new, but i never saw it before) called Volatile. It was made especally for CallBack and Com event functions, so I wanted to try that out. the advantage of this Keyword is, that you can run the Dll while you can do other things in autoit (AutoIt wont freeze/pause anymore while the dllcall is executed!)
      I made up a little example i want to share with you, the c source is compiled in MinGW, you need at least AutoIt
      Hope you like it, would be interested in some comments
    • By Frenchy
      I follow my project about the use of DirectInput with Autoit
      If i can create the interface correctly with the DirectInput8create Function

      I have a problem when i want to use Callback function to enum Devices. ("bad callee")

      i have Written this piece of code, but is it the the good syntax to callback the function _EnumJoystickProc?
      i have looked in this forum and Google, but no samples of code using callback and Objet, may be its no possible?
      Or there is a special syntax to callback function with autoit objet?

      Local $oDirectInput8 = ObjCreateInterface ( $sCLSID_DirectInput8 , $sIID_IDirectInput8 ,$dtagIDirectInput8 ) ; Create callback function Global $handle = DllCallbackRegister("_EnumJoystickProc", "BOOL", "ptr;ptr") $aa=$oDirectInput8.EnumDevices($DI8DEVCLASS_ALL,DllCallbackGetPtr($handle), 0, $DIEDFL_ATTACHEDONLY) ; MsgBox(0,hex($aa,8),$oDirectInput8) DllCallbackFree($handle) Exit Func _EnumJoystickProc($pDIinstance, $pContexte) MsgBox(0,"errrr","") Return $DIENUM_STOP EndFunc
  • Create New...