Как другие указали, необходимо создать прямую ссылку для каждого объекта Excel, который что Вы используете, и Маршал вызова. ReleaseComObject на той ссылке, как описано в эта статья KB. Также необходимо использовать попытку/наконец гарантировать, что ReleaseComObject всегда называют, даже когда исключение выдается. Т.е. вместо:
Worksheet sheet = excelApp.Worksheets(1)
... do something with sheet
необходимо сделать что-то как:
Worksheets sheets = null;
Worksheet sheet = null
try
{
sheets = excelApp.Worksheets;
sheet = sheets(1);
...
}
finally
{
if (sheets != null) Marshal.ReleaseComObject(sheets);
if (sheet != null) Marshal.ReleaseComObject(sheet);
}
также необходимо назвать Приложение. Выход прежде, чем выпустить Объект приложения, если Вы хотите, чтобы Excel закрылся.
, Как Вы видите, это быстро становится чрезвычайно громоздким, как только Вы пытаетесь сделать что-либо даже умеренно сложное. Я успешно разработал приложения.NET с простым классом обертки, который переносится, несколько простых манипуляций объектной моделью Excel (откройте рабочую книгу, запишите в Диапазон, сохраните/закройте рабочую книгу и т.д.). Класс обертки реализует IDisposable, тщательно реализует Маршала. ReleaseComObject на каждом объекте это использует и лобково не представляет объектов Excel остальной части приложения.
, Но этот подход не масштабируется хорошо для более сложных требований.
Это - большой дефицит COM Interop.NET. Для более сложных сценариев я серьезно рассмотрел бы запись DLL ActiveX в VB6 или другом неуправляемом языке, на который можно делегировать все взаимодействие с-proc COM-объектами, такими как Office. Можно тогда сослаться на этот DLL ActiveX из приложения.NET, и вещи будут намного легче, поскольку необходимо будет только выпустить эту ссылку.