ManagementEventWatcher - InvalidComObjectException, когда приложение существует
У меня есть.NET библиотека, которая использует ManagementEventWatcher
учебный класс. Моя библиотека одноразовая, поэтому обычно я оборачиваю ее в оператор использования и ManagementEventWatcher
класс распорядился бы моей библиотекой.
Моя проблема в том, что моя библиотека подвергается воздействию COM и используется в VB6, который не использует одноразовый шаблон. Если пользователь не вызывает утилиту dispose для библиотеки из своего приложения.net или не может из-за VB6, ManagementEventWatcher
класс бросит InvalidComObjectException
изнутри SinkForEventQuery.Cancel
Я не могу зафиксировать исключение, поэтому оно остается необработанным, что нехорошо. Есть ли какие-то обходные пути, которые я могу попробовать?
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:
1 ответ
У меня была такая же проблема только сегодня, в основном я не мог вызвать dispose для класса, и объект WMI не удалялся, выдавая мне ту же ошибку.
В итоге я реализовал другой интерфейс, а не IDisposable, предоставив два метода: Init и TearDown, и использовал этот метод для настройки моего MEW и его утилизации. Это немного хакерство, хотя, если пользователь класса не знает этого, он никогда не вызовет два метода, и ваш MEW никогда не запустится или не будет ликвидирован.
Другой способ может заключаться в том, чтобы подключить класс к событию, подобному "OnDestroy", и соответствующим образом отреагировать, разрушив объект MEW.
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;
}
}
РЕДАКТИРОВАТЬ: Да, я понимаю, что это не тот ответ, который вы искали, я не думаю, что есть способ избежать этого в любом случае, пользователь должен знать, как использовать класс...:/