2013-05-02 1 views
3

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

Я знаю, что это плохая практика для автоматизации Office, поскольку я видел информацию от Microsoft, что это не поддерживается. Это также указывается в ответе здесь opening excel error: System.Runtime.InteropServices.COMException (0x80080005): Retrieving the COM class factory for component with 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 Exception, он работает, но это не изящный результат. Любое хорошее решение для решения этой проблемы получит награду.

Другой Update:

решаемый делать это на окончательно блокировать

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 перед тем, как он будет использован снова.

+1

Это, как правило, причина, почему это не поддерживается. Это «почти» работает.Ошибка означает, что между процессом и процессом Excel.exe существует проблема связи. Вероятно, это проблема синхронизации, состояние гонки и т. Д. Одна вещь, которую вы можете попробовать, - это сериализовать все вызовы в Excel, чтобы не иметь более одного ожидающего запроса/вызова COM в Excel на том же компьютере. –

+0

Две вещи: можете ли вы переписать код, в котором вы создаете и удаляете электронные таблицы, вместо повторного запуска приложения? И если это слишком высокий уровень усилий, попробуйте установить интервал между экземплярами, чтобы дать время для освобождения ресурсов. – RandomUs1r

ответ

5

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

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

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

+0

спасибо, что сделали! – Raymund

7

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

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

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

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

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

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

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

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

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

+0

+1 за отличную информацию – Raymund

+0

за эту информацию. –

0

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

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

посмотрите эту статью, я надеюсь, что она сработает для вас.

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

рассматривает Shaz