Убийство Excel.EXE на сервере

Возможный дубликат:
Как правильно очистить объекты взаимодействия Microsoft в С#

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

Любые указатели были бы полезны?

Ответ 1

Извините, что сказал, и я не пытаюсь быть умным, но... не ставьте офис на сервер!!!

Что, если я правильно понял!:)

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

Сказав это, то же самое теперь для меня и Crystal Reports; -)

Ответ 2

Я согласен с тем, что не работает Office на сервере. Не то, чтобы у меня был выбор в этом вопросе:)

Одна вещь, которую следует помнить с помощью опции taskkill, заключается в том, что если вы специально не планируете ее (aka - singleton), у вас может быть несколько копий Excel (или любого другого приложения Office) и непреднамеренно закрыть неправильный экземпляр.

Также обратите внимание, что за http://support.microsoft.com/kb/257757

Microsoft в настоящее время не работает рекомендовать и не поддерживает, Автоматизация Microsoft Office приложения из любых автоматических, неинтерактивное клиентское приложение или компонент (включая ASP, ASP.NET, DCOM и NT Services), поскольку Office могут проявлять нестабильное поведение и/или тупика, когда Office запущен в этом окружающая среда.

В качестве альтернативы существует продукт под названием Aspose Cells, который предлагает продукт, предназначенный для программной работы с листом Excel в серверной среде. Как отказ от ответственности я никогда не использовал этот продукт лично, но об этом слышал несколько человек, с которыми я работал в прошлом.

Ответ 3

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

Вот некоторые хорошие ссылки, чтобы начать работу над созданием офисного документа с кодом. http://msdn.microsoft.com/en-us/magazine/cc163478.aspx http://msdn.microsoft.com/en-us/library/bb735940(office.12).aspx

Просто используйте SSIS на SQL Server. Он обеспечивает возможность экспорта в Excel. Не запускайте офис на сервере. Альтернативно тратить деньги на aspose или spreadsheetgear.

GC действительно работает, вы просто не используете его правильно следуете этому шаблону...

   private void killExcel()
        {
          xlApp.Quit();
          Marshal.ReleaseCOMObject(xlApp);
          if(xlApp != null)
          {
            xlApp = null;
          }
          GC.WaitForPendingFinalizers();
          GC.Collect();
          GC.WaitForPendingFinalizers();
          GC.Collect();
        }

получить рабочий класс Excel для реализации IDisposable, а затем применить метод killExcel() в методе Dispose.

UPDATE: Также обратите внимание, что иногда разработчик все еще видит, что программа Excel.exe работает в диспетчере задач. Прежде чем считать, что вышеуказанный код не работает, убедитесь, что процесс, который запускает код, также закрыт. В случае VSTO или COM addin проверьте, что экземпляр Word/powerpoint/other excel также закрыт, так как в процессе запуска все еще есть корень GC. Когда это будет закрыто, процесс Excel.exe закроется.

Ответ 4

Используете ли вы VSTO? Вы можете закрыть приложение Excel после того, как закончите с помощью excelobject.Quit();. Это сработало для меня, но я больше не использую Excel на стороне сервера.

Вы можете взглянуть на схему XML XML для создания файла Excel без самого Excel. Проверьте CarlosAg Excel Writer, который делает то же самое.

Ответ 5

У меня была аналогичная проблема. В то время как "taskkill excel.exe" или перечисление всех процессов "excel" и их убийство действительно работают, это убивает ВСЕ ПРОГРАММЫ Excel. Вам лучше убить только тот экземпляр, с которым вы сейчас работаете.

Вот код, который я использовал для этого. Он использует PInvoke (см. здесь), чтобы получить ProcessID из экземпляра Excel.Application(Me.ExcelInstance в примере ниже).

Dim ExcelPID As Integer
GetWindowThreadProcessId(New IntPtr(Me.ExcelInstance.Hwnd), ExcelPID)

If ExcelPID > 0 Then
   Dim ExcelProc As Process = Process.GetProcessById(ExcelPID)
   If ExcelProc IsNot Nothing Then ExcelProc.Kill()
End If

Пожалуйста, это может не работать на всех платформах из-за PInvoke... На сегодняшний день это единственный метод, который я нашел надежным. Я также попытался найти правильный PID, перечислив все процессы Excel и сравнив Process.MainModule.BaseAddress с Excel.Application.Hinstance.

'DO NOT USE THIS METHOD, for demonstration only    
For Each p as Process in ExcelProcesses
        Dim BaseAddr As Integer = p.MainModule.BaseAddress.ToInt32()
        If BaseAddr = Me.ExcelInstance.Hinstance Then
            p.Kill()
            Exit For
        End If
Next

Это не надежный способ найти правильный процесс, так как BaseAddress иногда кажется одинаковым для нескольких процессов (что приводит к убийству неправильного PID).

Ответ 7

:). Я записал свою перестрелку с помощью Excel здесь. У него также есть некоторые ссылки, которые я нашел после некоторых тяжелых поисков. Надеюсь, это поможет. В основном Excel - это боль, хотя он может быть автоматизирован.

Ответ 8

Я также не рекомендую использовать офисные приложения на сервере, кроме доступа к файлам mdb.

Я могу определенно понять, что есть моменты, когда это необходимо. В тех случаях Я бы рекомендовал следующее:

  • Создайте отдельный сервер, где это единственная функция. (Позвольте вам перезагружаться с минимальным воздействием).
  • Попросите сервер реализовать механизм запросов на очередность
  • Сохраняйте один поток, обрабатывающий очередь. Это дает вам возможность отслеживать офисное приложение, убивать его, если необходимо, и продолжать работу без каких-либо проблем с заданиями в очереди или другими приложениями.

Если вам абсолютно необходимо сделать это на том же сервере, то, по крайней мере, реализовать выше в нем собственный пул приложений.

Ограничение работы в очереди и только один экземпляр Excel (или любого другого офисного приложения) позволяют вам убить его с помощью TaskKill или .Kill() и не потерять работу.

Я верю, что если вы держите его в одном потоке, вам редко придется его убивать.

Ответ 9

Я использовал spreadsheetgear, чтобы генерировать отчеты XL на сервере, и он работает очень хорошо. Нам не нужно беспокоиться о процессе EXCEL.

Ответ 10

После завершения работы вам необходимо безопасно распоряжаться всеми объектами COM-взаимодействия. Под "all" я подразумеваю абсолютно all: значения свойств коллекции и т.д. Я создал объект стека и нажал объекты во время их установки:

Stack<object> comObjectsToRelease = new Stack<object>();
...
Log("Creating VBProject object.");
VBProject vbProject = workbook.VBProject;
comObjectsToRelease.Push(vbProject);
...
finally
{
    if(excel != null)
    {
        Log("Quiting Excel.");
        excel.Quit();
        excel = null;
    }
    while (comObjectsToRelease.Count > 0)
    {
        Log("Releasing {0} COM object.", comObjectsToRelease.GetType().Name);
        Marshal.FinalReleaseComObject(comObjectsToRelease.Pop());
    }               
    Log("Invoking garbage collection.");
    GC.Collect();
}

Если Excel все еще существует, вы должны убить его вручную.

Ответ 11

У меня была аналогичная проблема и я использовал следующий код:

System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcesses();
for (int i = 0; i < procs.Length; i++)
{
  if(procs[i].ProcessName == "EXCEL")
  {
    procs[i].Kill();
  }
}

Это сработало очень хорошо, но я действительно подумал бы о работе с Office на сервере.

Ответ 12

У меня на самом деле был вопрос, похожий на этот недостаток - Проверять зависание процесса Office при использовании Office Automation - некоторые ответы на этот вопрос могут быть полезны для вас.

Кроме того, я должен согласиться с тем, что говорят все остальные, в том, что касается защиты любых продуктов Office от сервера; однако, поскольку вы делаете Excel, может возникнуть необходимость генерировать документы Excel XML. Вы можете сделать это, не занимаясь автоматизацией Office, и процесс довольно прост. Для простых таблиц, основанных на сетке, я нашел, что это немного проще, чем пытаться автоматизировать его с помощью Excel. Office Open XML является достаточно мощным и позволяет более сложные отчеты, а также некоторые дополнительные усилия.

Ответ 14

Лучший подход - использовать специально созданную библиотеку, такую ​​как та, которая была создана в Aspose для создания таблиц или заполнения шаблонов. Следующим лучшим подходом является использование форматов xml для офиса, если это необходимо для ваших нужд. Легкий подход, который иногда подходит, - это создать HTML файл с одной таблицей в нем и называть его расширением .xls. Excel с радостью прочитает это, но он очень ограничен в том, что он может сделать.

Это варианты, которые я использовал (но не так много). Там также называется Microsoft Office Sharepoint Server, но я не знаю, насколько это действительно позволяет.

Тем не менее, ваша проблема возникает, потому что, когда вы вызываете обычные библиотеки Excel, вы фактически вращаете Excel полностью независимо от .Net и фактически просто работаете с прокси-библиотекой, чтобы поговорить с ним. Это почти то же самое, что и с WCF и сервисом. Вы не ожидали, что служба умрет только потому, что клиентское приложение было выполнено с ее помощью. Хуже того, Excel - это неуправляемый ресурс и не будет удаляться/завершаться/собирать мусор вообще..Net Runtime не знает о Excel, он просто знает об этих прокси. Application.quit - это то, что вам нужно, и вам может понадобиться явно освободить созданные COM-объекты.