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;
        }
    }

РЕДАКТИРОВАТЬ: Да, я понимаю, что это не тот ответ, который вы искали, я не думаю, что есть способ избежать этого в любом случае, пользователь должен знать, как использовать класс...:/

Другие вопросы по тегам