Windows允许创建(命名)Event objects。
一个事件(Windows中的同步原语)可以是自动重置类型(在这种情况下是could say it's kind of a semaphore),也可以是手动重置类型,在这种情况下,它会一直保持设置,直到有人重置它为止。
现在,从docs CreateEvent,OpenEvent,SetEvent等{{3}}开始,一旦事件创建,似乎无法确定,无论是自动重置还是重置。
我处于这种情况,其中一个进程创建一个命名的事件,第二个进程必须对此事件进行操作(它将传递名称,然后打开事件并最终发出信号)。由于事件应始终是手动重置事件,因为整个事情都有意义,我本来希望在第二个过程中添加一个检查,以确保 手动重置事件。有没有办法检查这个?
(是的,在我的情况下,它更像是一个很好的东西,因为如果任何代码创建一个自动重置事件然后将它传递给这个过程,它将是一个错误。但是错误发生了,并且如果我能发现它们就越好。)
答案 0 :(得分:5)
没有记录的方法可以做到这一点,但如果你冒险进入无证的土地,实际上并不难。 (为了您的目的,这应该没问题,因为它不会真正影响您的程序的功能。)
您需要做的第一件事是弄清楚给您的句柄是否是一个事件。你使用NtQueryObject。该功能记录在此处:http://msdn.microsoft.com/en-us/library/bb432383(v=vs.85).aspx。它附带了本机API的通常附带条款,它可能会在没有通知的情况下消失或更改。部分示例:
#include <winternl.h>
typedef NTSTATUS (NTAPI * PFN_NtQueryObject)(
HANDLE Handle,
OBJECT_INFORMATION_CLASS ObjectInformationClass,
PVOID ObjectInformation,
ULONG ObjectInformationLength,
PULONG ReturnLength );
HMODULE ntdll = GetModuleHandle( L"ntdll.dll" );
auto NtQueryObject = (PFN_NtQueryObject)GetProcAddress( ntdll, "NtQueryObject" );
NTSTATUS result = NtQueryObject(
eventHandle,
ObjectTypeInformation,
buffer,
length,
&length );
这将为您提供PUBLIC_OBJECT_TYPE_INFORMATION结构。如果对象实际上是一个事件,则TypeName字段将为“Event”。
接下来,调用NtQueryEvent来获取事件的类型。所有这些完全未记录。
typedef enum _EVENT_INFORMATION_CLASS {
EventBasicInformation
} EVENT_INFORMATION_CLASS, *PEVENT_INFORMATION_CLASS;
typedef enum _EVENT_TYPE {
NotificationEvent,
SynchronizationEvent
} EVENT_TYPE, *PEVENT_TYPE;
typedef struct _EVENT_BASIC_INFORMATION {
EVENT_TYPE EventType;
LONG EventState;
} EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION;
typedef NTSTATUS (NTAPI * PFN_NtQueryEvent)(
HANDLE EventHandle,
EVENT_INFORMATION_CLASS EventInformationClass,
PVOID EventInformation,
ULONG EventInformationLength,
PULONG ReturnLength );
auto NtQueryEvent = (PFN_NtQueryEvent)GetProcAddress( ntdll, "NtQueryEvent" );
EVENT_BASIC_INFORMATION info;
ULONG length = sizeof( info );
NTSTATUS result = NtQueryEvent(
eventHandle,
EventBasicInformation,
&info,
length,
&length );
现在,只需检查信息中的EventType字段即可。 “NotificationEvent”表示手动复位,“SynchronizationEvent”表示自动复位。
如果你想知道我是怎么想出第二部分的话,我没有。信息来自:http://undocumented.ntinternals.net/。请负责任地使用!
答案 1 :(得分:1)
在您的初始WaitForSingleObject( handle, 0 )
返回后立即致电WaitForSingleObject
。如果返回值为WAIT_TIMEOUT
,那么您知道它是自动重置事件,如果它是WAIT_OBJECT_0
将被返回并且它是手动重置事件。
这确实依赖于在两次调用之间设置的句柄,因此存在潜在的竞争条件,它不会检测到自动重置事件,但它应该在大多数时间工作。因为这是一个很好的,希望这就够了吗?