ManagementEventWatcher - InvalidComObjectException when application exists
I have build a .net library that uses the ManagementEventWatcher
class. My library is disposable, so normally I would开发者_开发技巧 wrap it in a using statement and the ManagementEventWatcher
class would get disposed by my library.
My issue is that my library is exposed to COM, and gets used in VB6 which doesn't use the disposable pattern. If a user does not call dispose on the library from within their .net application, or can't because of VB6, the ManagementEventWatcher
class will throw an InvalidComObjectException
from within SinkForEventQuery.Cancel
I can't capture the exception, so it remains unhandled, which is not good. Are there some workarounds I can try?
System.Runtime.InteropServices.InvalidComObjectException was unhandled
Message=COM object that has been separated from its underlying RCW cannot be used.
Source=mscorlib
StackTrace:
at System.StubHelpers.StubHelpers.StubRegisterRCW(Object pThis, IntPtr pThread)
at System.Management.IWbemServices.CancelAsyncCall_(IWbemObjectSink pSink)
at System.Management.SinkForEventQuery.Cancel()
at System.Management.ManagementEventWatcher.Stop()
at System.Management.ManagementEventWatcher.Finalize()
InnerException:
I had the same problem just today, basically I could not call dispose on the class and the WMI object was not being disposed, giving me the same error.
What I did in the end was implement a different interface rather than IDisposable, exposing two methods: Init and TearDown, and use those method to set up my MEW and dispose it. It is a bit of a hack though, if the user of the class does not know this he will never call the two methods and your MEW will never start or be disposed.
Another way could possibly be to have the class hook up to an event like "OnDestroy" and respond accordingly by tearing down the MEW object.
public void Init()
{
if (mew == null)
{
mew = new ManagementEventWatcher(query);
mew.EventArrived += mew_EventArrived;
mew.Start();
}
}
public void TearDown()
{
if (mew != null)
{
mew.Stop();
mew.Dispose();
mew = null;
}
}
EDIT: Yes I realize this is not the answer you were looking for, I don't think there is a way to avoid this anyway, the user must know how to use the class... :/
精彩评论