WMI and Quota violation exception

D

Dilip

Hi

I am using the following WMI code to watch for the termination of a
particular process. This code is running under Windows Vista.

public void WaitForDeath()
{
using (AutoResetEvent thisEvent = WatchForProcessDeath())
{
WaitHandle.WaitOne(thisEvent);
}
}

private AutoResetEvent WatchForProcessDeath()
{
AutoResetEvent evt = new AutoResetEvent(false);
string newQry =
"select * from __InstanceDeletionEvent within 2 where
TargetInstance ISA 'Win32_Process' and " +
"TargetInstance.Name = 'MyProcess.exe'";
ManagementEventWatcher mew = new ManagementEventWatcher(@"\\.\root
\CIMV2", newQry);
mew.EventArrived += delegate { evt.Set(); };
mew.Start();
return evt;
}

Our QA folks tested this functionality by calling WaitForDeath()
repeatedly in a tight loop. at some point, say after 3 hours or so,
we started getting a "Quota violation" exception of type
System.ManagementException on the Start() method of
ManagementEventWatcher.

I happened upon some posts related to this on the WMI newsgroup but I
am not clear how to solve this in my case.

1) Is this happening because of the query itself? If so, why does it
happen only after 3 hours and not right away?
2) Is this happening because I am not properly disposing of the
ManagementEventWatcher objects? In the EventArrived event I could
add:

mew.Stop();
mew.Dispose();

in addition to setting the autoreset event. I just don't know enough
about WMI to decide if it would help.

Can anyone help? (From past experience I really hope Mr. Willy
Denoyette sees this!)
 
W

Willy Denoyette [MVP]

Dilip said:
Hi

I am using the following WMI code to watch for the termination of a
particular process. This code is running under Windows Vista.

public void WaitForDeath()
{
using (AutoResetEvent thisEvent = WatchForProcessDeath())
{
WaitHandle.WaitOne(thisEvent);
}
}

private AutoResetEvent WatchForProcessDeath()
{
AutoResetEvent evt = new AutoResetEvent(false);
string newQry =
"select * from __InstanceDeletionEvent within 2 where
TargetInstance ISA 'Win32_Process' and " +
"TargetInstance.Name = 'MyProcess.exe'";
ManagementEventWatcher mew = new ManagementEventWatcher(@"\\.\root
\CIMV2", newQry);
mew.EventArrived += delegate { evt.Set(); };
mew.Start();
return evt;
}

Our QA folks tested this functionality by calling WaitForDeath()
repeatedly in a tight loop. at some point, say after 3 hours or so,
we started getting a "Quota violation" exception of type
System.ManagementException on the Start() method of
ManagementEventWatcher.

I happened upon some posts related to this on the WMI newsgroup but I
am not clear how to solve this in my case.

1) Is this happening because of the query itself? If so, why does it
happen only after 3 hours and not right away?
2) Is this happening because I am not properly disposing of the
ManagementEventWatcher objects? In the EventArrived event I could
add:

mew.Stop();
mew.Dispose();

in addition to setting the autoreset event. I just don't know enough
about WMI to decide if it would help.

Can anyone help? (From past experience I really hope Mr. Willy
Denoyette sees this!)



You need to stop the ManagementEventWatcher when done with it. The Quota
limit for *all* events that get handled on a Completion Port thread is 1000
which equals the maximum number of CP threads per process in .NET.
Why it only happens after 3 hours depends on the frequency they called the
method, call it in a tight loop and you won't have to wait longer than a
couple of seconds I guess.
Besides, it's preferable to use the Win32_ProcessStopTrace class on Vista
and higher, this class uses ETW which is really event driven while you are
using a polling mechanism under the covers.



Willy.
 
D

Dilip

You need to stop the ManagementEventWatcher when done with it. The Quota
limit for *all* events that get handled on a Completion Port thread is 1000
which equals the maximum number of CP threads per process in .NET.
Why it only happens after 3 hours depends on the frequency they called the
method, call it in a tight loop and you won't have to wait longer than a
couple of seconds I guess.

Actually, as I mentioned in my original post, this problem happened
after running this code in a tight loop for 3 hours but I guess thats
besides the point when there seems to be an obvious error in my code.
Besides, it's preferable to use the Win32_ProcessStopTrace class on Vista
and higher, this class uses ETW which is really event driven while you are
using a polling mechanism under the covers.

Thanks a ton for replying. I changed the code to call Stop() on
receiving the EventArrived event. I will have to test it on Monday.

Meanwhile, could you show me a small snippet on how to use
Win32_ProcessStopTrace class to watch for termination of a process?
You could also point me in the right direction and that'd be fine with
me.

thanks!
 
D

Dilip

You need to stop the ManagementEventWatcher when done with it. The Quota
limit for *all* events that get handled on a Completion Port thread is 1000
which equals the maximum number of CP threads per process in .NET.
Why it only happens after 3 hours depends on the frequency they called the
method, call it in a tight loop and you won't have to wait longer than a
couple of seconds I guess.
Besides, it's preferable to use the Win32_ProcessStopTrace class on Vista
and higher, this class uses ETW which is really event driven while you are
using a polling mechanism under the covers.

Willy.

Ok. It looks like all I have to do is replace my original
__InstanceDeletionEvent query with:

Select * from Win32_ProcessStopTrace where ProcessName='MyProcess.exe'

Am I right?
 
W

Willy Denoyette [MVP]

Dilip said:
Ok. It looks like all I have to do is replace my original
__InstanceDeletionEvent query with:

Select * from Win32_ProcessStopTrace where ProcessName='MyProcess.exe'

Am I right?



No, "select" for a trace events, you need to select the property of interest
in the eventhandler, something like:

using(ManagementEventWatcher w = new
ManagementEventWatcher("Win32_ProcessStopTrace"))
{
w.EventArrived += ProcessStopped;
w.Start();
Console.ReadLine(); // block main thread for test purposes
w.Stop();
}
}
static void ProcessStopped(object sender, EventArrivedEventArgs e) {

if((string)e.NewEvent.Properties["processname"].Value ==
"notepad.exe")
{
Console.WriteLine("Process: {0}, Stopped with Code: {1}",
(int)(uint)e.NewEvent.Properties["ProcessId"].Value,
(int)(uint)e.NewEvent.Properties["ExitStatus"].Value);
}
}


Willy.
 
Top