Получение System.Runtime.InteropServices.COMException Ошибка в стороне сервера, сгенерированной Excel

У нас есть веб-приложение, которое генерирует таблицы Excel и запускает макросы на стороне сервера. Затем он отправляет их разным лицам по электронной почте. Это часть унаследованного стиля отчетности, который мы переносим, ​​но все еще поддерживаем в нашем новом приложении, которое мы представили в качестве веб-сайта в IIS.

Я знаю, что делать автоматизацию Office - плохая практика, поскольку я видел информацию от Microsoft, что это не поддерживается. Это также указано в ответе, открывающем здесь ошибку Excel: System.Runtime.InteropServices.COMException (0x80080005): получение фабрики классов COM для компонента с CLSID

В любом случае, если коротко, отчеты Excel создаются в пакетном сценарии, который может генерировать от 3 до 300 отчетов, отправляемых разным людям. Генерация отчетов работает нормально, пока не достигнет 15-20-го пункта, а затем вылетит, это дает мне ошибку ниже

System.Runtime.InteropServices.COMException (0x80080005): Retrieving the COM class factory for component with CLSID {00024500-0000-0000-C000-000000000046} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).
   at System.Runtime.Remoting.RemotingServices.AllocateUninitializedObject(RuntimeType objectType)
   at System.Runtime.Remoting.Activation.ActivationServices.CreateInstance(RuntimeType serverType)
   at System.Runtime.Remoting.Activation.ActivationServices.IsCurrentContextOK(RuntimeType serverType, Object[] props, Boolean bNewObj)
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at Ci.Infrastructure.Reporting.ReportProviderExcel.RunReport()

Что может быть не так? Первые отчеты оказались успешными, и я знаю, что это не шаблоны Excel, поскольку при повторном запуске все неудачные отчеты будут успешно продолжаться, а когда генерируется отчет с 15 по 20, он снова выдает ошибку.

Обновление: Мы знаем, что просили проблемы, но мне нужно решение, чтобы решить проблему. Помните, что это для устаревших вещей, которые мы перестанем поддерживать в будущем, но в переходный период нам это нужно.

Мы пробовали сериализацию все еще не работает. Мы пытались перевести нить в поток, генерирующую отчет Excel, когда он попадает в исключение COM, это работает, но это не элегантный результат. Любое хорошее решение для решения этой проблемы будет предоставлено за вознаграждение.

Еще одно обновление:

Решено сделать это на блоке finally

finally
{
    if (dataWorksheet != null)
    {
        Marshal.ReleaseComObject(dataWorksheet);
    }

    if (worksheets != null)
    {
        Marshal.ReleaseComObject(worksheets);
    }

    if (workbook != null)
    {
        workbook.Close(false);
        Marshal.ReleaseComObject(workbook);
    }

    if (workbooks != null)
    {
        workbooks.Close();
        Marshal.ReleaseComObject(workbooks);
    }

    if (excel != null)
    {
        excel.Quit();
        Marshal.ReleaseComObject(excel);
    }
}

Как и то, что сказал MarkWalls, закройте каждый из экземпляров Excel как единицу работы, которая полностью очищает процесс EXCEL перед его повторным использованием.

4 ответа

Решение

У меня была такая проблема. Приведенные выше ответы похожи на правильные - у вас, вероятно, по существу есть пул собранных без мусора экземпляров Excel, которые объединяют сервер.

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

Еще одна мысль, которую мы пытались, но в итоге не использовали, заключалась в создании файлов CSV, а не файлов Excel. Если вам просто нужны данные, то CSV намного легче. У нас были сложные формулы в рабочих тетрадях, без которых просто невозможно обойтись.

Ошибка выполнения сервера

Вы не показали много исследований, вы всегда должны смотреть в журнал событий приложений Windows, чтобы получить более подробную информацию об этом. Я просто предполагаю, что вы страдаете от типичной проблемы с использованием Excel из программы.NET.

Это описание ошибки всегда точное, COM может буквально не запускать Excel.exe. Это почти всегда, потому что операционная система исчерпывает ресурсы, пул памяти ядра обычно тот, который заканчивается. Обычно вы можете понять почему, запустив Диспетчер задач (надеюсь, он все еще работает), и посмотрите на вкладку Процессы. Хорошие шансы, что вы увидите десятки копий Excel.exe. Если вы не можете запустить диспетчер задач, следите за списком при перезапуске приложения.

Excel - это "жирный" процесс, он использует много ресурсов операционной системы. Он был действительно написан для настольного использования, только один экземпляр Excel.exe будет работать. Даже если вы запустите его снова, запускается второй экземпляр и замечает, что другой экземпляр уже запущен. Он говорит с первым и попросит его сделать то, что вы хотели, например открыть другой документ. И выходит, оставляя только 1-й ход. Этот же механизм не работает при использовании COM. Не без того, чтобы вы позаботились об этом сами, создавая только один экземпляр и заставляя его выполнять всю работу.

Есть веские причины, по которым эти экземпляры Excel.exe не закрываются, когда вы прекращаете их использовать. У вас проблема со сборкой мусора в вашей программе. Коллектор не запускается достаточно часто. Попасть в такую ​​проблему легко, вы, как правило, выполняете всю тяжелую работу в Excel и никогда не выделяете достаточно объектов для запуска сборщика мусора.

Это означает, что Excel может выйти только тогда, когда его экземпляр интерфейса будет собирать мусор. Управление памятью в сценарии COM-взаимодействия сильно отличается, это подсчет ссылок. Когда вы начинаете использовать интерфейс, такой как Приложение, то счетчик ссылок увеличивается. Он выключается, когда запускается финализатор. Что не произойдет до тех пор, пока после сборки мусора.

Многие программисты решают эту проблему, вызывая Marshal.ReleaseComObject(), чтобы уменьшить количество ссылок. Многие из этих программистов также сталкиваются с этой проблемой, она не будет работать, если вы не вызовете ее для каждой ссылки на интерфейс. Есть ли такие, которые не видны в программе.

Лучший способ сделать это - принудительно запустить сборку мусора после того, как вы закончили работу с Excel. Установите любую ссылку интерфейса на null и вызовите GC.Collect() + GC.WaitForPendingFinalizers(). Обязательно протестируйте это для сборки Release без отладчика. И обязательно сделайте это в методе, отдельном от метода, который использует интерфейсы Excel. Диспетчер задач скажет вам, впереди ли вы.

Запускать Excel на сервере по-прежнему плохая идея, но если этот подход работает для вас, у вас будет немного передышки.

Вы действительно напрашиваетесь на неприятности. Посмотрите, поможет ли это: http://blogs.msdn.com/b/adioltean/archive/2005/06/24/432519.aspx

Вы можете достичь своего решения, используя асинхронное программирование с использованием ASP.NET, MSMQ и Windows Service, для длительных процессов, таких как генерация отчетов.

поскольку веб-архитектура требует продолжения выполнения процесса / потока, поэтому системный сбой часто возникает при наличии функции создания отчетов, которая генерирует большое количество отчетов.

взгляните на следующую статью, я надеюсь, что она вам подойдет.

http://www.codeproject.com/Articles/8809/How-to-do-asynchronous-programming-using-ASP-NET-M

С уважением Shaz

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