Working with windows events

Практическое руководство. Вызов и обработка событий How to: Raise and Consume Events

В примерах в этом разделе показано, как работать с событиями. The examples in this topic show how to work with events. Даны примеры делегата EventHandler, делегата EventHandler и пользовательского делегата, иллюстрирующие события как с данными, так и без. They include examples of the EventHandler delegate, the EventHandler delegate, and a custom delegate, to illustrate events with and without data.

В примерах используются понятия, описанные в руководстве по событиям. The examples use concepts described in the Events article.

Пример Example

В первом примере показано, как вызывать и использовать событие, не содержащее данные. The first example shows how to raise and consume an event that doesn’t have data. Он содержит класс Counter с событием ThresholdReached . It contains a class named Counter that has an event named ThresholdReached . Это событие возникает, когда значение счетчика больше порогового значения или равно ему. This event is raised when a counter value equals or exceeds a threshold value. Делегат EventHandler связан с событием, потому что данные события не предоставляются. The EventHandler delegate is associated with the event, because no event data is provided.

Пример Example

В следующем примере показано, как вызывать и использовать событие, предоставляющее данные. The next example shows how to raise and consume an event that provides data. Делегат EventHandler связан с событием; предоставляется экземпляр объекта данных пользовательского события. The EventHandler delegate is associated with the event, and an instance of a custom event data object is provided.

Пример Example

В следующем примере показано объявление делегата для события. The next example shows how to declare a delegate for an event. Имя делегата — ThresholdReachedEventHandler . The delegate is named ThresholdReachedEventHandler . Это всего лишь пример. This is just an illustration. Как правило, не требуется объявлять делегат для события, поскольку можно использовать делегат EventHandler или EventHandler . Typically, you do not have to declare a delegate for an event, because you can use either the EventHandler or the EventHandler delegate. Объявлять делегат необходимо только в редких случаях, например чтобы сделать класс доступным для устаревшего кода, который не может использовать универсальные классы. You should declare a delegate only in rare scenarios, such as making your class available to legacy code that cannot use generics.

Windows Events

Events are typically used for troubleshooting application and driver software.

  • Prior to WindowsВ Vista, you would use either Event Tracing for Windows (ETW) or Event Logging to log events.
  • WindowsВ Vista introduced a new event model that unified both the Event Tracing for Windows (ETW) and Windows Event Log API.
  • WindowsВ 10 introduces TraceLogging which builds on ETW and provides a simplified way to instrument code for native, .NET and WinRT developers.

The new TraceLogging model allows you to include structured data with events, correlate events, and does not require a separate instrumentation manifest XML file.

The WindowsВ Vista model uses an XML manifest to define the events that you want to publish. Events can be published to a channel or an ETW session. You can publish the events to the following types of channels: Admin, Operational, Analytic and Debug. If you use only ETW to enable the publisher, you do not need to specify channels in your manifest. For complete details on writing a manifest, see Writing an Instrumentation Manifest, and for information on channels, see Defining Channels.

To register your event publisher and to publish events, you use the ETW API. For details, see Providing Events and Developing a Provider. The event publisher will automatically write the events to the channels specified in the manifest if they are enabled.

If you want to control the events that an event publisher publishes at a finer level of granularity, use the ETW API. For example, if the manifest defines both write and read events, you can enable only the write events. An event can also specify a level value such as warning or error, so you can limit the events that are written to those that specify the error level. For details, see Controlling Event Tracing Sessions. The events are written to the session’s log file.

Consuming events involves retrieving the events from an event channel, an event log file (.evtx or .evt files), a trace file (.etl files), or a real-time ETW session. To consume events from an ETW trace file or a real-time ETW session, use the trace data helper (TDH) functions in ETW to consume the events. You can also use TDH to read the event metadata. For details, see Consuming Events. To consume events from an event channel or an event log file, use the Windows Event Log functions to query or subscribe to events. For more information, see Querying for Events or Subscribing to Events.

Читайте также:  Hp color laser 150a mac os

Prior to WindowsВ Vista, you must use Event Tracing for Windows or Event Logging to publish and consume events.

Handle and raising events

Events in .NET are based on the delegate model. The delegate model follows the observer design pattern, which enables a subscriber to register with and receive notifications from a provider. An event sender pushes a notification that an event has happened, and an event receiver receives that notification and defines a response to it. This article describes the major components of the delegate model, how to consume events in applications, and how to implement events in your code.

Events

An event is a message sent by an object to signal the occurrence of an action. The action can be caused by user interaction, such as a button click, or it can result from some other program logic, such as changing a property’s value. The object that raises the event is called the event sender. The event sender doesn’t know which object or method will receive (handle) the events it raises. The event is typically a member of the event sender; for example, the Click event is a member of the Button class, and the PropertyChanged event is a member of the class that implements the INotifyPropertyChanged interface.

To define an event, you use the C# event or the Visual Basic Event keyword in the signature of your event class, and specify the type of delegate for the event. Delegates are described in the next section.

Typically, to raise an event, you add a method that is marked as protected and virtual (in C#) or Protected and Overridable (in Visual Basic). Name this method On EventName; for example, OnDataReceived . The method should take one parameter that specifies an event data object, which is an object of type EventArgs or a derived type. You provide this method to enable derived classes to override the logic for raising the event. A derived class should always call the On EventName method of the base class to ensure that registered delegates receive the event.

The following example shows how to declare an event named ThresholdReached . The event is associated with the EventHandler delegate and raised in a method named OnThresholdReached .

Delegates

A delegate is a type that holds a reference to a method. A delegate is declared with a signature that shows the return type and parameters for the methods it references, and it can hold references only to methods that match its signature. A delegate is thus equivalent to a type-safe function pointer or a callback. A delegate declaration is sufficient to define a delegate class.

Delegates have many uses in .NET. In the context of events, a delegate is an intermediary (or pointer-like mechanism) between the event source and the code that handles the event. You associate a delegate with an event by including the delegate type in the event declaration, as shown in the example in the previous section. For more information about delegates, see the Delegate class.

.NET provides the EventHandler and EventHandler delegates to support most event scenarios. Use the EventHandler delegate for all events that do not include event data. Use the EventHandler delegate for events that include data about the event. These delegates have no return type value and take two parameters (an object for the source of the event, and an object for event data).

Delegates are multicast, which means that they can hold references to more than one event-handling method. For details, see the Delegate reference page. Delegates provide flexibility and fine-grained control in event handling. A delegate acts as an event dispatcher for the class that raises the event by maintaining a list of registered event handlers for the event.

For scenarios where the EventHandler and EventHandler delegates do not work, you can define a delegate. Scenarios that require you to define a delegate are very rare, such as when you must work with code that does not recognize generics. You mark a delegate with the C# delegate and Visual Basic Delegate keyword in the declaration. The following example shows how to declare a delegate named ThresholdReachedEventHandler .

Event data

Data that is associated with an event can be provided through an event data class. .NET provides many event data classes that you can use in your applications. For example, the SerialDataReceivedEventArgs class is the event data class for the SerialPort.DataReceived event. .NET follows a naming pattern of ending all event data classes with EventArgs . You determine which event data class is associated with an event by looking at the delegate for the event. For example, the SerialDataReceivedEventHandler delegate includes the SerialDataReceivedEventArgs class as one of its parameters.

Читайте также:  Как увеличить количество ядер процессора windows 10

The EventArgs class is the base type for all event data classes. EventArgs is also the class you use when an event does not have any data associated with it. When you create an event that is only meant to notify other classes that something happened and does not need to pass any data, include the EventArgs class as the second parameter in the delegate. You can pass the EventArgs.Empty value when no data is provided. The EventHandler delegate includes the EventArgs class as a parameter.

When you want to create a customized event data class, create a class that derives from EventArgs, and then provide any members needed to pass data that is related to the event. Typically, you should use the same naming pattern as .NET and end your event data class name with EventArgs .

The following example shows an event data class named ThresholdReachedEventArgs . It contains properties that are specific to the event being raised.

Event handlers

To respond to an event, you define an event handler method in the event receiver. This method must match the signature of the delegate for the event you are handling. In the event handler, you perform the actions that are required when the event is raised, such as collecting user input after the user clicks a button. To receive notifications when the event occurs, your event handler method must subscribe to the event.

The following example shows an event handler method named c_ThresholdReached that matches the signature for the EventHandler delegate. The method subscribes to the ThresholdReached event.

Static and dynamic event handlers

.NET allows subscribers to register for event notifications either statically or dynamically. Static event handlers are in effect for the entire life of the class whose events they handle. Dynamic event handlers are explicitly activated and deactivated during program execution, usually in response to some conditional program logic. For example, they can be used if event notifications are needed only under certain conditions or if an application provides multiple event handlers and run-time conditions define the appropriate one to use. The example in the previous section shows how to dynamically add an event handler. For more information, see Events (in Visual Basic) and Events (in C#).

Raising multiple events

If your class raises multiple events, the compiler generates one field per event delegate instance. If the number of events is large, the storage cost of one field per delegate may not be acceptable. For those situations, .NET provides event properties that you can use with another data structure of your choice to store event delegates.

Event properties consist of event declarations accompanied by event accessors. Event accessors are methods that you define to add or remove event delegate instances from the storage data structure. Note that event properties are slower than event fields, because each event delegate must be retrieved before it can be invoked. The trade-off is between memory and speed. If your class defines many events that are infrequently raised, you will want to implement event properties. For more information, see How to: Handle Multiple Events Using Event Properties.

Working with windows events

As you may (and should) know Event Log is your first place to look for explanations on why server/client is behaving the way it is behaving. You simply start the Event Viewer and you browse thru different logs. Be it Windows, Exchange or other logs you will find yourself in a situation there are thousands of logs logged each minute on busy servers. In crisis situation you would open up Event Viewer

Find what you were looking for and close your case. But it’s not always that easy… there are times where you have to query multiple servers or run your checks daily looking for particular events happening on your infrastructure.

Microsoft brings you Get-WinEvent as a standard to work with Windows Event Log since some time now. There are other methods but Microsoft really wants you to use this one as it supports all the bells and whistles provided by Microsoft. And for the most part it does it’s just pretty good. You can query things just the way you want. But let’s work on the example. Lets assume we want to check when the last few patches were installed on AD1 machine, and that you want to get it from Event Logs.

Читайте также:  Астра линукс домен windows

You had to write simple query for Setup Event Log and look for Event ID number 2. Finally using Format-List * gives us all information about the events.

In example above we first checked all data for the Event, and then subsequently verified the information we need, and just queried for exact results we needed. While the results provide us a nice way to get what we needed…. there is one problem. The Message field contains a lot of additional information we don’t need. What if we’re interested in particular Windows Update and not all updates installed?

We would now need to get the Message, parse it, split it in multiple chunks and output information. This means a lot of additional work that is subject to break. Of course you could always use Like and search for particular information just like below.

But this is a simple Event. There are far complicated events that may not be easy to parse like that. What if there is a simpler way?

Lets take a look what PSEventViewer can do on the very same Event Log query as above.

Noticed something different? How all the relevant information been provided to you on a silver platter?

Much easier ha? Now the query for particular KB could be even simpler…

PSEventViewer (Get-Events) is really useful PowerShell wrapper around Get-WinEvent. Provided above example just shows one of the features you may be interested in (simple way of getting “hidden” events data). The other 2 important features are:

First feature is an important one. While Get-WinEvent can query results in fast and efficient way things get complicated when you want to query 2, 5, 10 servers. You may think it’s really not worth the effort to introduce parallel processing into reading Event Logs but I assure you it makes all the difference. In my special module that queries all AD servers for certain Events it was able to bring down the time from 50 minutes to under 18 minutes. For my other Client which has few more AD servers and a bit different architecture with heavier load the script changed the time to query all AD Servers from 15 hours to just around 3 hours. That’s a huge difference. Of course it wasn’t the only change I did but it was crucial one.

The second thing I did for the other script was to query event logs just once for multiple ID’s instead of querying multiple times for 1-5 ID’s at the time. I’ve noticed that whether you ask for 5 ID’s or 20 of them the time difference is minimal. So if your initial query took 1 minute to execute to get 5 Event ID’s on 5 AD Servers and you wanted to query it 4 times for different sets of ID’s it would take 1 minute * 5 servers * 4 times. It would take 20 minutes to query 5 servers, 4 times. With new approach you make query once, you parallel all servers at same time and just wait for output to come in more or less 2 minutes (granted there can be other things in play here..). You may say here…

But wait, you could always query Get-WinEvent for multiple events!

That is true! Until you reach 23 events…

While the error message says:

No events were found that match the specified selection criteria.

That’s far from truth. You will get same message whether you query 2 MB Security Log and same when you query 50GB Security Log. You will even get similar response in Event Viewer so it does seem like a limitation of Windows.

With Get-Events you get slightly different story. For the purpose of demonstration what happens I’ve used the Verbose parameter.

As you can see the story is quite different. Verbose message shows us there were 32 Event ID’s to query and that the function split the events in 2 chunks and actually run them in parallel. One finished quickly because the event log didn’t contain much events to process in regards to those ID’s. The other one took over 1 minute and returned 2780 events. Keep in mind those 2780 events are processed and provided with those hidden fields. You can’t compare it with clean Get-WinEvent which would return a bit quicker as it doesn’t do the post processing that Get-Events does. You get few more kinks thou.

While you can use the script in a standard way by downloading it from GitHub, putting it in right places and getting it to run…there is much simpler way. Since the script was published to PowerShell Gallery you can simply install the module and run it from anywhere. Just use Install-Module PSEventViewer.

Оцените статью