Modify

#3963 closed Feature Request (Completed)

_WinAPI_OpenEvent function missing in WinAPIProc.au3

Reported by: kleiza44@… Owned by: Jpm
Milestone: 3.3.17.0 Component: AutoIt
Version: Severity: None
Keywords: Cc:

Description

Please add _WinAPI_OpenEvent function that allows to check global events from windows.

_WinAPI_CreateEvent function by documentation should allow to open events, but if global event was created using different application, then script won't be able to access it.

Function in windows: https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createeventa?redirectedfrom=MSDN&f1url=%3FappId%3DDev10IDEF1%26l%3DEN-US%26k%3Dk(CreateEvent)%3Bk(DevLang-C)%3Bk(TargetOS-WINDOWS)%26rd%3Dtrue

Function written in AutoIT which works in my case (Maybe positions of parameters could be changed like in already written AutoIT functions, to keep same structure in all AutoIT functions):

Func _WinAPI_OpenEvent($sName = "", $dwDesiredAccess = 0x1F0003 , $bInheritHandle = True)
	If $sName = "" Then $sName = Null

	Local $aCall = DllCall("kernel32.dll", "handle", "OpenEventW", "struct*", $dwDesiredAccess, "bool", $bInheritHandle, _
			"wstr", $sName)
	If @error Then Return SetError(@error, @extended, 0)

	Local $iLastError = _WinAPI_GetLastError()
	If $iLastError Then Return SetExtended($iLastError, 0)

	Return $aCall[0]
EndFunc   ;==>_WinAPI_OpenEvent

If this function can be added, then it would make sense to add it to documentation as well like in here : https://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_CreateEvent.htm

Attachments (0)

Change History (9)

comment:1 follow-up: Changed 16 months ago by Jpm

Hi,
Can you explain why the first paraameter can be optional (not described in MSDN) ?
can you post an example so I can add it in the doc?
Thanks for the help

comment:2 in reply to: ↑ 1 Changed 16 months ago by anonymous

Replying to Jpm:

Hi,
Can you explain why the first paraameter can be optional (not described in MSDN) ?
can you post an example so I can add it in the doc?
Thanks for the help

Hi,
I just copied the _WinAPI_CreateEvent implementation and replaced parameters/names to make it work with OpenEvent() function. My example is probably incorrect, but since I provide all parameters myself when calling it, it was working for me.

Sorry I am not advanced enough to write clean code as in documentation, but for that I have modified my script to get global event from third party software and it looks like this :

#include <WinAPIHObj.au3>
#include <WinAPIProc.au3>
#include <Date.au3>

Func _WinAPI_OpenEvent($dwDesiredAccess, _ ; Not provided value should translate to EVENT_ALL_ACCESS
        $bInheritHandle, _ ; Usually is false
        $sName) ; If you provide empty string or null, it will create a nameless event

        If $sName = "" Then $sName = Null

        Local $aCall = DllCall("kernel32.dll", "handle", "OpenEventW", "struct*", $dwDesiredAccess, "bool", $bInheritHandle, "wstr", $sName)
        If @error Then Return SetError(@error, @extended, 0)

        Local $iLastError = _WinAPI_GetLastError()
        If $iLastError Then Return SetExtended($iLastError, 0)

        Return $aCall[0]
EndFunc   ;==>_WinAPI_OpenEvent


Global $Event = _WinAPI_OpenEvent(0x1F0003, _ ;Value is EVENT_ALL_ACCESS
        False, "Global\HeartBeatEvent") ;Get global event handle
Local $iEvent
Local $cycle = True

HotKeySet("{ESC}", "_Exit")


While $cycle = True
        $iEvent = _WinAPI_WaitForSingleObject($Event, 1000) ;Get event from handle
        Switch $iEvent
                Case -1         ;WAIT_FAILED
                        ConsoleWrite(_Now() & " WAIT_FAILED" & @CRLF)
                        $ErrMsg = _WinAPI_GetLastErrorMessage(@extended)
                        ConsoleWrite("Result:" & $Event & @CRLF & $ErrMsg & @CRLF)
                        ExitLoop
                Case 0          ;WAIT_OBJECT_0
                        _WinAPI_ResetEvent($Event)
                        ConsoleWrite(_Now() & " Event appeared as expected." & @CRLF)
                Case 0x00000102 ;WAIT_TIMEOUT
                        ConsoleWrite(_Now() & " Event not appeared." & @CRLF)
                Case 0x00000080 ;WAIT_ABANDONED
                        ConsoleWrite(_Now() & " WAIT_ABANDONED" & @CRLF)
                        ExitLoop
        EndSwitch
        Sleep(1000)
WEnd    ;==>While


Func _Exit()
                $cycle = False
EndFunc ;==>_Exit

Please let me know if I can help you somehow more.

Last edited 15 months ago by mLipok (previous) (diff)

comment:3 Changed 16 months ago by Jpm

Thanks,
I still wondering when openinf with Null is helpfull.
Can you provide me an example?

comment:4 Changed 16 months ago by Jpm

I recheck your example it is not working on my system
PLrase try with a correct checking of the result

#include <WinAPIHObj.au3>
#include <WinAPIProc.au3>
#include <Date.au3>

Func _WinAPI_OpenEvent($sName, _ ; If you provide empty string or null, it will create a nameless event
                $dwDesiredAccess = 0x1F0003, _ ; Not provided value should translate to EVENT_ALL_ACCESS
                $bInheritHandle = False) ; Usually is false

        If $sName = "" Then $sName = Null

        Local $aCall = DllCall("kernel32.dll", "handle", "OpenEventW", "struct*", $dwDesiredAccess, "bool", $bInheritHandle, "wstr", $sName)
        If @error Then Return SetError(@error, @extended, 0)

        Local $iLastError = _WinAPI_GetLastError()
        If $iLastError Then Return SetExtended($iLastError, 0)

        Return $aCall[0]
EndFunc   ;==>_WinAPI_OpenEvent

Local $iEvent, $sErrMsg
Local $bCycle = True
HotKeySet("{ESC}", "_Exit")

Global $g_hEvent = _WinAPI_OpenEvent("Global\HeartBeatEvent", 0x1F0003, _ ;Value is EVENT_ALL_ACCESS
                False) ;Get global event handle
Local $iExtended = @extended
If $iExtended Then
        $sErrMsg = _WinAPI_GetErrorMessage($iExtended)
        ConsoleWrite("_WinAPI_OpenEvent() = " & $g_hEvent & @CRLF & $sErrMsg & @CRLF)
        Exit
EndIf

While $bCycle = True
        $iEvent = _WinAPI_WaitForSingleObject($g_hEvent, 1000) ;Get event from handle
        Switch $iEvent
                Case -1        ;WAIT_FAILED
                        $sErrMsg = _WinAPI_GetErrorMessage($iExtended)
                        ConsoleWrite("Result:" & $iEvent & "(WAIT_FAILED)" & @CRLF & $sErrMsg & @CRLF)
                        ExitLoop
                Case 0        ;WAIT_OBJECT_0
                        _WinAPI_ResetEvent($g_hEvent)
                        ConsoleWrite(_Now() & " Event appeared as expected." & @CRLF)
                Case 0x00000102    ;WAIT_TIMEOUT
                        ConsoleWrite(_Now() & " Event not appeared." & @CRLF)
                Case 0x00000080    ;WAIT_ABANDONED
                        ConsoleWrite(_Now() & " WAIT_ABANDONED" & @CRLF)
                        ExitLoop
        EndSwitch
        Sleep(1000)
WEnd    ;==>While


Func _Exit()
        $bCycle = False
EndFunc   ;==>_Exit

Last edited 15 months ago by mLipok (previous) (diff)

comment:5 Changed 16 months ago by anonymous

Hi! It seems a small error escaped you attention:
in

Local $aRet = DllCall("kernel32.dll", "handle", "OpenEventW", "struct*", $iDesired...

there should be "dword" instead of "struct*"

Local $aRet = DllCall("kernel32.dll", "handle", "OpenEventW", "dword", $iDesired...

Also, there was a wrong comment, stating that if an empty string is given to $sName, it will create an nameless event; that is incorrect; OpenEvent does not create events! and with empty $sName always returns 0x00000000.

Here's corrected version; this should be in WinAPIProc.au3:

Global Const $EVENT_ALL_ACCESS = 0x001F0003
Func _WinAPI_OpenEvent($sName, $iDesiredAccess = $EVENT_ALL_ACCESS, $bInheritHandle = False)    
        if $iDesiredAccess=Default OR $iDesiredAccess=-1 then $iDesiredAccess = $EVENT_ALL_ACCESS
        Local $aRet = DllCall("kernel32.dll", "handle", "OpenEventW", "dword", $iDesiredAccess, "bool", $bInheritHandle, "wstr", $sName)
        Return SetError(@error, @extended, @error ? False : $aRet[0])
EndFunc

This could be used eg for interprocess communication between two+ scripts (together with _WinApi_[create/set/reset]Event(...)), since the created events are global and acccessable by name.

comment:6 Changed 16 months ago by anonymous

acktchully, it seems more sensible that $bInheritHandle by default should be True! Sorry about that.
from MSDN:
(https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-openeventa)

...

[in] bInheritHandle

If this value is TRUE, processes created by this process will inherit the handle.
Otherwise, the processes do not inherit this handle.

comment:7 Changed 16 months ago by anonymous

(the code provided in comment 5 is placed by its anonymous author in the Public Domain, if this could even matter for such a measly teeny tiny wrapper!)

comment:8 Changed 16 months ago by Jpm

Thanks for the correction, but "Global\HeartBeatEvent" does work on my system.
What can be another $sEvent working for any system as I plan to put the script as an example in the help

Version 0, edited 16 months ago by Jpm (next)

comment:9 Changed 15 months ago by Jpm

  • Milestone set to 3.3.17.0
  • Owner set to Jpm
  • Resolution set to Completed
  • Status changed from new to closed

Added by revision [13003] in version: 3.3.17.0

Guidelines for posting comments:

  • You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
  • In-depth discussions should take place on the forum.

For more information see the full version of the ticket guidelines here.

Add Comment

Modify Ticket

Action
as closed The owner will remain Jpm.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.