Как очистить COM-ссылки в .NET, когда приложение будет запущено?

Я работаю над .NET-программой, которая запускает новый экземпляр Excel, выполняет некоторую работу, а затем завершает работу, но должна покинуть Excel. Позже, когда программа запустится снова, она попытается подключиться к предыдущему экземпляру.

Каков наилучший способ справиться с выпуском COM-объектов в этой ситуации? Если я не делаю «ReleaseComObject» в объекте приложения в первый раз, то во втором запуске получить активный объект, а затем, наконец, освободить объект com, у меня есть утечка памяти?

Следующий упрощенный код иллюстрирует то, что я пытаюсь сделать:

private Microsoft.Office.Interop.Excel.Application xlsApp; private Microsoft.Office.Interop.Excel.Workbook xlsWb; public void RunMeFirst() { //Start a new instance System.Type oSEType = Type.GetTypeFromProgID("Excel.Application"); xlsApp = Activator.CreateInstance(oSEType); xlsWb = xlsApp.Workbooks.Open("C:\\test1.xls"); //Do some stuff xlsWb.Close(false); Cleanup(ref xlsWb); //Do not quit Excel here //No Cleanup of xlsApp here? Is this OK? System.Environment.Exit(0); } public void RunMeSecond() { //Hook into existing instance xlsApp = Marshal.GetActiveObject("Excel.Application"); xlsWb = xlsApp.Workbooks.Open("C:\\test2.xls"); //Do some stuff xlsWb.Close(false); Cleanup(ref xlsWb); xlsApp.Quit(); Cleanup(ref xlsApp); System.Environment.Exit(0); } public void Cleanup(ref object theObj) { GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); Marshal.FinalReleaseComObject(theObj); theObj = null; } 

благодаря

В общем, при работе с Office PIA я обнаружил, что подобные проблемы с не выпущенными объектами возникают, когда у вас есть переменные экземпляра, содержащие объекты COM. В вашем случае это будут xlsApp и xlsWb . Вам не нужно оставлять приложение Excel для освобождения объектов, но вам необходимо выполнить следующие процедуры очистки:

 Marshal.FinalReleaseComObject(xlsWb); xlsWb = null; Marshal.FinalReleaseComObject(xlsApp); xlsApp = null; GC.Collect(); 

Локальные переменные, содержащие объекты COM, похоже, не вызывают этой проблемы, а только переменные экземпляра. Надеюсь, это поможет!

Я немного запутался – в конце RunMeFirst вы выходите из процесса, а RunMeSecond запускается в другом процессе из первого метода или того же процесса?

В любом случае я бы изменил ваш код так, чтобы xlsWb локально и просто сделал следующее:

 public void RunMeFirst() { System.Type oSEType = Type.GetTypeFromProgID("Excel.Application"); xlsApp = Activator.CreateInstance(oSEType); Workbook xlsWb = xlsApp.Workbooks.Open("C:\\test1.xls"); // Do stuff xlsWb.Close(false); System.Environment.Exit(0); } 

Вы действительно не должны называть какие-либо из методов ReleaseComObject кроме определенных обстоятельств (например, в серверных приложениях, где все COM-объекты будут использоваться, и поэтому очень важно как можно скорее освободить объекты). Обычный механизм очистки объекта COM должен просто состоять в том, чтобы позволить им выйти из области видимости, и в этом случае объект COM будет выпущен с использованием той же магии, которую использует GC (я считаю, что он очищается по мере запуска финализатора, но Я не уверен на этом на 100%).

Причина, по которой его хорошая идея в области xlsWb локально (а не как член класса или статический член) состоит в том, что члены класса будут очищаться только после очистки класса, а статические члены никогда не будут очищены до тех пор, пока appdomain не будет выгружен. Если вам нужно очистить объект COM, на который ссылается статическое поле, то способ сделать это – установить для статического поля значение null чтобы базовый COM-объект мог быть очищен правилами определения GC:

 xlsWb = null; 

Также не должно быть реальной необходимости называть GC.Collect по тем же причинам – Майк Розенблюм дает справедливое объяснение, почему он вызывает GC.Collect и ReleaseComObject , но не имеет никакого реального обоснования того, почему он не просто удовлетворен тем, что позволяет мусору сборщик выполняет свою работу. Как я уже сказал, бывают ситуации, когда вам может потребоваться больше контроля над выпуском COM-объектов, однако это исключение, а не правило.

Вы также можете найти чтение Marshal.ReleaseComObject считается опасным полезным.

  • Выгрузка COM-объектов C #
  • Ошибка MS Office PIA Com Interop
  • Microsoft Office Interop Excel VS Библиотека объектов Microsoft Excel
  • Внезапная ошибка кода в Visual Studio Express 2010
  • Как я могу использовать классы из VisualBasic-Express в VBA для проектов Excel или Access?
  • Как получить определенный диапазон в Excel через COM Interop?
  • Закрытие приложения Excel без ссылок com? Excel продолжает работать в фоновом режиме
  • писать длинный текст в книге excel с помощью ошибки interop throws?
  • В Excel VBA как перенести ключевые переменные на «потерю состояния» (без записи в ячейку или файл)?
  • Как проверить орфографию, но не показывать диалог проверки орфографии?
  • C # COM Interop Excel: сохранение ведущих нулей в текстовых строках
  • Давайте будем гением компьютера.