/// <summary> /// <para>Waits for the next event that matches the specified query to arrive, and /// then returns it.</para> /// </summary> /// <returns> /// <para>A <see cref='System.Management.ManagementBaseObject'/> representing the /// newly arrived event.</para> /// </returns> /// <remarks> /// <para>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.</para> /// </remarks> 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.GetIWbemServices().ExecNotificationQuery_( query.QueryLanguage, query.QueryString, options.Flags, options.GetContext(), out enumWbem); //Set security on enumerator if (status >= 0) { securityHandler.Secure(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 = enumWbem.Next_(timeout, (uint)options.BlockSize, tempArray, out 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... - TODO: what should happen if there was a timeout //but at least some objects were returned ?? 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 = 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); }
/// <summary> /// <para>Waits for the next event that matches the specified query to arrive, and /// then returns it.</para> /// </summary> /// <returns> /// <para>A <see cref='System.Management.ManagementBaseObject'/> representing the /// newly arrived event.</para> /// </returns> /// <remarks> /// <para>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.</para> /// </remarks> public ManagementBaseObject WaitForNextEvent() { ManagementBaseObject obj = null; Initialize(); #pragma warning disable CA2002 lock (this) #pragma warning restore CA2002 { 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 { //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])); } } } 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, WmiNetUtilsHelper.GetErrorInfo_f()); } } } return(obj); }
/// <summary> /// <para>Waits until the next event that matches the specified query arrives, /// and returns it</para> /// </summary> /// <remarks> /// If the event watcher object contains /// options with a specified timeout, this API will wait for the next event only for /// the specified time. If not, the API will block until the next event occurs. /// </remarks> public ManagementBaseObject WaitForNextEvent() { Trace.WriteLine("Entering 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.GetIWbemServices().ExecNotificationQuery_( query.QueryLanguage, query.QueryString, options.Flags, options.GetContext(), out enumWbem); //Set security on enumerator if ((status & 0x80000000) == 0) { securityHandler.Secure(enumWbem); } } if ((status & 0x80000000) == 0) { if ((cachedCount - cacheIndex) == 0) //cache is empty - need to get more objects { // TODO - due to TLBIMP restrictions IEnumWBemClassObject.Next will // not work with arrays - have to set count to 1 #if false enumWbem.Next((int)options.Timeout.TotalMilliseconds, (uint)options.BlockCount, out cachedObjects, out cachedCount); #else IWbemClassObjectFreeThreaded cachedObject = cachedObjects[0]; int timeout = (ManagementOptions.InfiniteTimeout == options.Timeout) ? (int)tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE : (int)options.Timeout.TotalMilliseconds; status = enumWbem.Next_(timeout, 1, out cachedObject, out cachedCount); cacheIndex = 0; if ((status & 0x80000000) == 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 & 0x80000000) == 0) { obj = new ManagementBaseObject(cachedObjects[cacheIndex]); cacheIndex++; } } } catch (Exception e) { // BUGBUG : securityHandler.Reset()? if (e is ManagementException) { throw; //just let it propagate } ManagementException.ThrowWithExtendedInfo(e); } finally { securityHandler.Reset(); Trace.WriteLine("Returning from WaitForNextEvent..."); } if ((status & 0xfffff000) == 0x80041000) { ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); } else if ((status & 0x80000000) != 0) { Marshal.ThrowExceptionForHR(status); } } return(obj); }