Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Wmi / managed / System / Management / ManagementEventWatcher.cs / 1305376 / ManagementEventWatcher.cs
using System; using System.Collections; using System.Runtime.InteropServices; using WbemClient_v1; using System.Diagnostics; using System.ComponentModel; using System.Threading; namespace System.Management { ////// public delegate void EventArrivedEventHandler(object sender, EventArrivedEventArgs e); ///Represents the method that will handle the ///event. /// public delegate void StoppedEventHandler (object sender, StoppedEventArgs e); //CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC// ///Represents the method that will handle the ///event. /// ///Subscribes to temporary event notifications /// based on a specified event query. ////// //CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC// [ToolboxItem(false)] public class ManagementEventWatcher : Component { //fields private ManagementScope scope; private EventQuery query; private EventWatcherOptions options; private IEnumWbemClassObject enumWbem; private IWbemClassObjectFreeThreaded[] cachedObjects; //points to objects currently available in cache private uint cachedCount; //says how many objects are in the cache (when using BlockSize option) private uint cacheIndex; //used to walk the cache private SinkForEventQuery sink; // the sink implementation for event queries private WmiDelegateInvoker delegateInvoker; //Called when IdentifierChanged() event fires private void HandleIdentifierChange(object sender, IdentifierChangedEventArgs e) { // Invalidate any [....] or async call in progress Stop(); } //default constructor ///using System; /// using System.Management; /// /// // This example demonstrates how to subscribe to an event using the ManagementEventWatcher object. /// class Sample_ManagementEventWatcher /// { /// public static int Main(string[] args) { /// /// //For the example, we'll put a class into the repository, and watch /// //for class deletion events when the class is deleted. /// ManagementClass newClass = new ManagementClass(); /// newClass["__CLASS"] = "TestDeletionClass"; /// newClass.Put(); /// /// //Set up an event watcher and a handler for the event /// ManagementEventWatcher watcher = new ManagementEventWatcher( /// new WqlEventQuery("__ClassDeletionEvent")); /// MyHandler handler = new MyHandler(); /// watcher.EventArrived += new EventArrivedEventHandler(handler.Arrived); /// /// //Start watching for events /// watcher.Start(); /// /// // For the purpose of this sample, we delete the class to trigger the event /// // and wait for two seconds before terminating the consumer /// newClass.Delete(); /// /// System.Threading.Thread.Sleep(2000); /// /// //Stop watching /// watcher.Stop(); /// /// return 0; /// } /// /// public class MyHandler { /// public void Arrived(object sender, EventArrivedEventArgs e) { /// Console.WriteLine("Class Deleted = " + /// ((ManagementBaseObject)e.NewEvent["TargetClass"])["__CLASS"]); /// } /// } /// } ///
///Imports System /// Imports System.Management /// /// ' This example demonstrates how to subscribe an event using the ManagementEventWatcher object. /// Class Sample_ManagementEventWatcher /// Public Shared Sub Main() /// /// ' For the example, we'll put a class into the repository, and watch /// ' for class deletion events when the class is deleted. /// Dim newClass As New ManagementClass() /// newClass("__CLASS") = "TestDeletionClass" /// newClass.Put() /// /// ' Set up an event watcher and a handler for the event /// Dim watcher As _ /// New ManagementEventWatcher(New WqlEventQuery("__ClassDeletionEvent")) /// Dim handler As New MyHandler() /// AddHandler watcher.EventArrived, AddressOf handler.Arrived /// /// ' Start watching for events /// watcher.Start() /// /// ' For the purpose of this sample, we delete the class to trigger the event /// ' and wait for two seconds before terminating the consumer /// newClass.Delete() /// /// System.Threading.Thread.Sleep(2000) /// /// ' Stop watching /// watcher.Stop() /// /// End Sub /// /// Public Class MyHandler /// Public Sub Arrived(sender As Object, e As EventArrivedEventArgs) /// Console.WriteLine("Class Deleted = " & _ /// CType(e.NewEvent("TargetClass"), ManagementBaseObject)("__CLASS")) /// End Sub /// End Class /// End Class ///
////// Initializes a new instance of the ///class. /// /// public ManagementEventWatcher() : this((ManagementScope)null, null, null) {} //parameterized constructors ///Initializes a new instance of the ///class. For further /// initialization, set the properties on the object. This is the default constructor. /// /// AnInitializes a new instance of the ///class when given a WMI event query. object representing a WMI event query, which determines the events for which the watcher will listen. /// /// public ManagementEventWatcher ( EventQuery query) : this(null, query, null) {} ///The namespace in which the watcher will be listening for /// events is the default namespace that is currently set. ////// /// A WMI event query, which defines the events for which the watcher will listen. ///Initializes a new instance of the ///class when given a WMI event query in the /// form of a string. /// public ManagementEventWatcher ( string query) : this(null, new EventQuery(query), null) {} ///The namespace in which the watcher will be listening for /// events is the default namespace that is currently set. ////// /// AInitializes a new instance of the ////// class that listens for events conforming to the given WMI event query. object representing the scope (namespace) in which the watcher will listen for events. /// An object representing a WMI event query, which determines the events for which the watcher will listen. public ManagementEventWatcher( ManagementScope scope, EventQuery query) : this(scope, query, null) {} /// /// /// The management scope (namespace) in which the watcher will listen for events. /// The query that defines the events for which the watcher will listen. public ManagementEventWatcher( string scope, string query) : this(new ManagementScope(scope), new EventQuery(query), null) {} ///Initializes a new instance of the ////// class that listens for events conforming to the given WMI event query. For this /// variant, the query and the scope are specified as strings. /// /// The management scope (namespace) in which the watcher will listen for events. /// The query that defines the events for which the watcher will listen. /// AnInitializes a new instance of the ///class that listens for /// events conforming to the given WMI event query, according to the specified options. For /// this variant, the query and the scope are specified as strings. The options /// object can specify options such as a timeout and context information. object representing additional options used to watch for events. public ManagementEventWatcher( string scope, string query, EventWatcherOptions options) : this(new ManagementScope(scope), new EventQuery(query), options) {} /// /// /// AInitializes a new instance of the ///class /// that listens for events conforming to the given WMI event query, according to the specified /// options. For this variant, the query and the scope are specified objects. The /// options object can specify options such as timeout and context information. object representing the scope (namespace) in which the watcher will listen for events. /// An object representing a WMI event query, which determines the events for which the watcher will listen. /// An object representing additional options used to watch for events. public ManagementEventWatcher( ManagementScope scope, EventQuery query, EventWatcherOptions options) { if (null != scope) this.scope = ManagementScope._Clone(scope, new IdentifierChangedEventHandler(HandleIdentifierChange)); else this.scope = ManagementScope._Clone(null, new IdentifierChangedEventHandler(HandleIdentifierChange)); if (null != query) this.query = (EventQuery)query.Clone(); else this.query = new EventQuery(); this.query.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); if (null != options) this.options = (EventWatcherOptions)options.Clone(); else this.options = new EventWatcherOptions(); this.options.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); enumWbem = null; cachedCount = 0; cacheIndex = 0; sink = null; delegateInvoker = new WmiDelegateInvoker (this); } /// /// ~ManagementEventWatcher () { // Ensure any outstanding calls are cleared Stop (); if (null != scope) scope.IdentifierChanged -= new IdentifierChangedEventHandler (HandleIdentifierChange); if (null != options) options.IdentifierChanged -= new IdentifierChangedEventHandler (HandleIdentifierChange); if (null != query) query.IdentifierChanged -= new IdentifierChangedEventHandler (HandleIdentifierChange); } // // Events // ///Ensures that outstanding calls are cleared. This is the destructor for the object. ////// public event EventArrivedEventHandler EventArrived; ///Occurs when a new event arrives. ////// public event StoppedEventHandler Stopped; // //Public Properties // ///Occurs when a subscription is canceled. ////// ///Gets or sets the scope in which to watch for events (namespace or scope). ////// public ManagementScope Scope { get { return scope; } set { if (null != value) { ManagementScope oldScope = scope; scope = (ManagementScope)value.Clone (); // Unregister ourselves from the previous scope object if (null != oldScope) oldScope.IdentifierChanged -= new IdentifierChangedEventHandler(HandleIdentifierChange); //register for change events in this object scope.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); //the scope property has changed so act like we fired the event HandleIdentifierChange(this, null); } else throw new ArgumentNullException("value"); } } ///The scope in which to watch for events (namespace or scope). ////// ///Gets or sets the criteria to apply to events. ////// public EventQuery Query { get { return query; } set { if (null != value) { ManagementQuery oldQuery = query; query = (EventQuery)value.Clone (); // Unregister ourselves from the previous query object if (null != oldQuery) oldQuery.IdentifierChanged -= new IdentifierChangedEventHandler(HandleIdentifierChange); //register for change events in this object query.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); //the query property has changed so act like we fired the event HandleIdentifierChange(this, null); } else throw new ArgumentNullException("value"); } } ///The criteria to apply to the events, which is equal to the event query. ////// ///Gets or sets the options used to watch for events. ////// public EventWatcherOptions Options { get { return options; } set { if (null != value) { EventWatcherOptions oldOptions = options; options = (EventWatcherOptions)value.Clone (); // Unregister ourselves from the previous scope object if (null != oldOptions) oldOptions.IdentifierChanged -= new IdentifierChangedEventHandler(HandleIdentifierChange); cachedObjects = new IWbemClassObjectFreeThreaded[options.BlockSize]; //register for change events in this object options.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); //the options property has changed so act like we fired the event HandleIdentifierChange(this, null); } else throw new ArgumentNullException("value"); } } ///The options used to watch for events. ////// ///Waits for the next event that matches the specified query to arrive, and /// then returns it. ////// ///A ///representing the /// newly arrived event. /// public ManagementBaseObject WaitForNextEvent() { ManagementBaseObject obj = null; Initialize (); lock(this) { SecurityHandler securityHandler = Scope.GetSecurityHandler(); int status = (int)ManagementStatus.NoError; try { if (null == enumWbem) //don't have an enumerator yet - get it { //Execute the query status = scope.GetSecuredIWbemServicesHandler( Scope.GetIWbemServices() ).ExecNotificationQuery_( query.QueryLanguage, query.QueryString, options.Flags, options.GetContext (), ref enumWbem); } if (status >= 0) { if ((cachedCount - cacheIndex) == 0) //cache is empty - need to get more objects { #if true //Because Interop doesn't support custom marshalling for arrays, we have to use //the "DoNotMarshal" objects in the interop and then convert to the "FreeThreaded" //counterparts afterwards. IWbemClassObject_DoNotMarshal[] tempArray = new IWbemClassObject_DoNotMarshal[options.BlockSize]; int timeout = (ManagementOptions.InfiniteTimeout == options.Timeout) ? (int) tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE : (int) options.Timeout.TotalMilliseconds; status = scope.GetSecuredIEnumWbemClassObjectHandler(enumWbem).Next_(timeout, (uint)options.BlockSize, tempArray, ref cachedCount); cacheIndex = 0; if (status >= 0) { //Convert results and put them in cache. Note that we may have timed out //in which case we might not have all the objects. If no object can be returned //we throw a timeout exception... - if (cachedCount == 0) ManagementException.ThrowWithExtendedInfo(ManagementStatus.Timedout); for (int i = 0; i < cachedCount; i++) cachedObjects[i] = new IWbemClassObjectFreeThreaded(Marshal.GetIUnknownForObject(tempArray[i])); } #else //This was workaround when using TLBIMP we couldn't pass in arrays... IWbemClassObjectFreeThreaded cachedObject = cachedObjects[0]; int timeout = (ManagementOptions.InfiniteTimeout == options.Timeout) ? (int) tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE : (int) options.Timeout.TotalMilliseconds; status = scope.GetSecuredIEnumWbemClassObjectHandler(enumWbem).Next_(timeout, 1, out cachedObjects, out cachedCount); cacheIndex = 0; if (status >= 0) { //Create ManagementObject for result. Note that we may have timed out //in which case we won't have an object if (null == cachedObject) ManagementException.ThrowWithExtendedInfo(ManagementStatus.Timedout); cachedObjects[0] = cachedObject; } #endif } if (status >= 0) { obj = new ManagementBaseObject(cachedObjects[cacheIndex]); cacheIndex++; } } } finally { securityHandler.Reset(); } if (status < 0) { if ((status & 0xfffff000) == 0x80041000) ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); else Marshal.ThrowExceptionForHR(status); } } return obj; } //******************************************** //Start //******************************************** ///If the event watcher object contains options with /// a specified timeout, the API will wait for the next event only for the specified /// amount of time; otherwise, the API will be blocked until the next event occurs. ////// public void Start() { Initialize (); // Cancel any current event query Stop (); // Submit a new query SecurityHandler securityHandler = Scope.GetSecurityHandler(); IWbemServices wbemServices = scope.GetIWbemServices(); try { sink = new SinkForEventQuery(this, options.Context, wbemServices); if (sink.Status < 0) { Marshal.ThrowExceptionForHR(sink.Status); } // For async event queries we should ensure 0 flags as this is // the only legal value int status = scope.GetSecuredIWbemServicesHandler(wbemServices).ExecNotificationQueryAsync_( query.QueryLanguage, query.QueryString, 0, options.GetContext(), sink.Stub); if (status < 0) { if (sink != null) { sink.ReleaseStub(); sink = null; } if ((status & 0xfffff000) == 0x80041000) ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); else Marshal.ThrowExceptionForHR(status); } } finally { securityHandler.Reset(); } } //******************************************** //Stop //******************************************** ///Subscribes to events with the given query and delivers /// them, asynchronously, through the ///event. /// public void Stop() { //For semi-synchronous, release the WMI enumerator to cancel the subscription if (null != enumWbem) { Marshal.ReleaseComObject(enumWbem); enumWbem = null; FireStopped (new StoppedEventArgs (options.Context, (int)ManagementStatus.OperationCanceled)); } // In async mode cancel the call to the sink - this will // unwind the operation and cause a Stopped message if (null != sink) { sink.Cancel (); sink = null; } } private void Initialize () { //If the query is not set yet we can't do it if (null == query) throw new InvalidOperationException(); if (null == options) Options = new EventWatcherOptions (); //If we're not connected yet, this is the time to do it... lock (this) { if (null == scope) Scope = new ManagementScope (); if (null == cachedObjects) cachedObjects = new IWbemClassObjectFreeThreaded[options.BlockSize]; } lock (scope) { scope.Initialize (); } } internal void FireStopped (StoppedEventArgs args) { try { delegateInvoker.FireEventToDelegates (Stopped, args); } catch { } } internal void FireEventArrived (EventArrivedEventArgs args) { try { delegateInvoker.FireEventToDelegates (EventArrived, args); } catch { } } } internal class SinkForEventQuery : IWmiEventSource { private ManagementEventWatcher eventWatcher; private object context; private IWbemServices services; private IWbemObjectSink stub; // The secured IWbemObjectSink private int status; private bool isLocal; public int Status {get {return status;} set {status=value;}} public SinkForEventQuery (ManagementEventWatcher eventWatcher, object context, IWbemServices services) { this.services = services; this.context = context; this.eventWatcher = eventWatcher; this.status = 0; this.isLocal = false; // determine if the server is local, and if so don't create a real stub using unsecap if((0==String.Compare(eventWatcher.Scope.Path.Server, ".", StringComparison.OrdinalIgnoreCase)) || (0==String.Compare(eventWatcher.Scope.Path.Server, System.Environment.MachineName, StringComparison.OrdinalIgnoreCase))) { this.isLocal = true; } if(MTAHelper.IsNoContextMTA()) // Bug#110141 - Checking for MTA is not enough. We need to make sure we are not in a COM+ Context HackToCreateStubInMTA(this); else { // // [marioh, RAID: 111108] // Ensure we are able to trap exceptions from worker thread. // ThreadDispatch disp = new ThreadDispatch ( new ThreadDispatch.ThreadWorkerMethodWithParam ( HackToCreateStubInMTA ) ) ; disp.Parameter = this ; disp.Start ( ) ; // Thread thread = new Thread(new ThreadStart(HackToCreateStubInMTA)); // thread.ApartmentState = ApartmentState.MTA; // thread.Start(); // thread.Join(); } } void HackToCreateStubInMTA(object param) { SinkForEventQuery obj = (SinkForEventQuery) param ; object dmuxStub = null; obj.Status = WmiNetUtilsHelper.GetDemultiplexedStub_f (obj, obj.isLocal, out dmuxStub); obj.stub = (IWbemObjectSink) dmuxStub; } internal IWbemObjectSink Stub { get { return stub; } } public void Indicate(IntPtr pWbemClassObject) { Marshal.AddRef(pWbemClassObject); IWbemClassObjectFreeThreaded obj = new IWbemClassObjectFreeThreaded(pWbemClassObject); try { EventArrivedEventArgs args = new EventArrivedEventArgs(context, new ManagementBaseObject(obj)); eventWatcher.FireEventArrived(args); } catch { } } public void SetStatus ( int flags, int hResult, String message, IntPtr pErrObj) { #if TODO_ERROBJ_NEVER_USED IWbemClassObjectFreeThreaded errObj = null; if(pErrObj != IntPtr.Zero) { Marshal.AddRef(pErrObj); errObj = new IWbemClassObjectFreeThreaded(pErrObj); } #endif // try { // Fire Stopped event eventWatcher.FireStopped(new StoppedEventArgs(context, hResult)); //This handles cases in which WMI calls SetStatus to indicate a problem, for example //a queue overflow due to slow client processing. //Currently we just cancel the subscription in this case. // if ( hResult != (int)tag_WBEMSTATUS.WBEM_E_CALL_CANCELLED && hResult != (int)tag_WBEMSTATUS.WBEM_S_OPERATION_CANCELLED) ThreadPool.QueueUserWorkItem(new WaitCallback(Cancel2));// Cancel(); // } catch { } } // void Cancel2(object o) { // // Try catch the call to cancel. In this case the cancel is being done without the client // knowing about it so catching all exceptions is not a bad thing to do. If a client calls // Stop (which calls Cancel), they will still recieve any exceptions that may have occured. // try { Cancel(); } catch { } } internal void Cancel () { if (null != stub) { lock(this) { if (null != stub) { int status = services.CancelAsyncCall_(stub); // Release prior to throwing an exception. ReleaseStub(); if (status < 0) { if ((status & 0xfffff000) == 0x80041000) ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); else Marshal.ThrowExceptionForHR(status); } } } } } internal void ReleaseStub () { if (null != stub) { lock(this) { /* * We force a release of the stub here so as to allow * unsecapp.exe to die as soon as possible. * however if it is local, unsecap won't be started */ if (null != stub) { try { System.Runtime.InteropServices.Marshal.ReleaseComObject(stub); stub = null; } catch { } } } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.Cancels the subscription whether it is synchronous or asynchronous. ///
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ClassHandlersStore.cs
- MasterPageCodeDomTreeGenerator.cs
- basenumberconverter.cs
- SessionEndingCancelEventArgs.cs
- ContentPresenter.cs
- LayoutExceptionEventArgs.cs
- GenericParameterDataContract.cs
- oledbmetadatacollectionnames.cs
- sqlnorm.cs
- TemplateInstanceAttribute.cs
- GuidelineCollection.cs
- WmlCalendarAdapter.cs
- ConfigurationException.cs
- DefaultWorkflowTransactionService.cs
- HttpWebRequest.cs
- UnsafeNativeMethods.cs
- FontFamily.cs
- RelationalExpressions.cs
- EntityUtil.cs
- DataGridViewTextBoxColumn.cs
- SoapEnumAttribute.cs
- xmlfixedPageInfo.cs
- CallbackException.cs
- QilScopedVisitor.cs
- ImportOptions.cs
- LogRecordSequence.cs
- CodeObjectCreateExpression.cs
- ResourceContainer.cs
- CompressStream.cs
- InstalledFontCollection.cs
- SvcMapFile.cs
- PrintSchema.cs
- InternalConfigRoot.cs
- BrushValueSerializer.cs
- ShapeTypeface.cs
- TransformGroup.cs
- SortQuery.cs
- HwndHostAutomationPeer.cs
- CellParaClient.cs
- TextRunProperties.cs
- UInt16Storage.cs
- DataContext.cs
- JoinSymbol.cs
- TextChange.cs
- TdsParameterSetter.cs
- WebServiceEnumData.cs
- DataServiceBehavior.cs
- Point.cs
- FontStyle.cs
- SafeNativeMethods.cs
- FormsAuthenticationConfiguration.cs
- DataBinder.cs
- WindowsIdentity.cs
- Avt.cs
- SoapBinding.cs
- RequestCachePolicy.cs
- UInt64.cs
- LabelDesigner.cs
- HttpInputStream.cs
- Helpers.cs
- GlobalProxySelection.cs
- ExecutionEngineException.cs
- MultiPartWriter.cs
- Label.cs
- DebuggerAttributes.cs
- CustomWebEventKey.cs
- PersistenceContext.cs
- OSFeature.cs
- StrokeNodeEnumerator.cs
- Light.cs
- SessionIDManager.cs
- ToReply.cs
- ComboBoxItem.cs
- DodSequenceMerge.cs
- NamespaceQuery.cs
- BindingBase.cs
- StdRegProviderWrapper.cs
- SeparatorAutomationPeer.cs
- IItemProperties.cs
- RootBuilder.cs
- Module.cs
- XmlSchemaAnyAttribute.cs
- xdrvalidator.cs
- Trigger.cs
- SqlDataReaderSmi.cs
- Script.cs
- ClonableStack.cs
- WebResourceAttribute.cs
- SortKey.cs
- ObjectDataSourceMethodEditor.cs
- CodeMethodReturnStatement.cs
- ObjectDisposedException.cs
- MenuRendererClassic.cs
- AppSecurityManager.cs
- BamlRecordHelper.cs
- NotSupportedException.cs
- DataSourceNameHandler.cs
- validation.cs
- OutputCacheSettingsSection.cs
- Conditional.cs