Почему убивать процесс Excel - это плохо?

Я видел много статей и вопросов о том, как быть уверенным, что Excel действительно завершает работу, когда вы этого хотите, и процесс не остается в живых. Вот статья базы знаний с описанием проблемы и рекомендуемым решением Microsoft. По сути:

'close files

'Quit Excel
xlApp.quit()

'Release and collect garbage
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlApp)
GC.Collect()
GC.WaitForPendingFinalizers()

Многие не рекомендуют убивать процесс; См. Как правильно очистить объекты взаимодействия Excel и Общие сведения о сборке мусора в .NET

С другой стороны, многие люди не рекомендуют использовать GC.Collect. См. Что плохого в использовании GC.Collect ()?

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

<System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, _
ByRef lpdwProcessId As Integer) As Integer
    End Function

Sub testKill()

    'start the application
    Dim xlApp As Object = CreateObject("Excel.Application")

    'do some work with Excel

    'close any open files

    'get the window handle
    Dim xlHWND As Integer = xlApp.hwnd

    'this will have the process ID after call to GetWindowThreadProcessId
    Dim ProcIdXL As Integer = 0

    'get the process ID
    GetWindowThreadProcessId(xlHWND, ProcIdXL)

    'get the process
    Dim xproc As Process = Process.GetProcessById(ProcIdXL)

    'Quit Excel
    xlApp.quit()

    'Release
    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlApp)

    'set to nothing
    xlApp = Nothing

    'kill the process if still running
    If Not xproc.HasExited Then
        xproc.Kill()
    End If

End Sub

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

Многие также скажут, что с хорошим кодом мне не нужно убивать процесс. Может быть, но это не отвечает на вопрос «Почему плохо убивать процесс?» После закрытия файлов, выхода из Excel и освобождения объектов; почему было бы плохо просто убедиться, что процесс завершен?

Изменить: также, что на самом деле остается после выхода из Excel? Если Excel был виден, он, похоже, завершил работу нормально, исчезнув из поля зрения и с панели задач. Так действительно ли Excel закрылся или нет. Мне кажется, что Excel действительно завершил работу и у нас работает только пустая оболочка процесса. Кто-нибудь может это прокомментировать?

Изменить: мне интересно отметить, что сборщик мусора (он же сборщик мусора) через GC.Collect () GC.WaitForPendingFinalizers () фактически освобождает оболочку процесса, которая остается после выхода Excel. Подтверждает ли это мое предположение, что пустая оболочка процесса на самом деле является мусором?

Изменить: только что нашел отличный веб-сайт по проблеме: 50 способов убить Excel


person D_Bester    schedule 22.07.2013    source источник
comment
Убить процесс - все равно что выключить компьютер, выдернув шнур питания из стены. Конечно, это работает, но это неправильный способ закрыть программу.   -  person Cody Gray    schedule 22.07.2013
comment
@CodyGray Современные машины предназначены для восстановления после выдергивания шнура питания в разумных пределах. Вы потеряете что-то только в том случае, если еще не сохранили это. Думаю, ему интересно, применимо ли то же самое в современном Excel?   -  person Toby Allen    schedule 22.07.2013
comment
@CodyGray Но что на самом деле может случиться в моем случае с Excel? Я потеряю информацию? Компьютер меня возненавидит? Собственно Excel уже вышел. Так не правда ли, что единственное, что осталось, - это объекты памяти, которые отказались умирать?   -  person D_Bester    schedule 22.07.2013
comment
@Toby Я не согласен. Да, была проделана работа, чтобы попытаться не допустить, чтобы что-то пошло так же плохо, как раньше, но это все еще не означает, что это действительный способ выключить вашу систему. Инженеры по безопасности работают над автомобилями, чтобы убедиться, что вы тоже не погибнете в аварии, но это не значит, что вам не нужно безопасно водить машину. Итак, да, Windows обычно очищается после завершения процессов, но это не значит, что это правильно.   -  person Cody Gray    schedule 22.07.2013
comment
Что, если у пользователя открыты другие листы Excel? Кроме того, проблема не только в том, что Excel остается открытым, когда вы неправильно управляете объектами Interop, но и в том, что он действует более медленно и ненадежно, если вы пренебрегаете управлением объектами.   -  person Christian Sauer    schedule 22.07.2013
comment
@ChristianSauer На самом деле пользователь никогда не взаимодействует с моим скрытым экземпляром Excel. И мой код никогда не завершает работу ни с одним другим экземпляром.   -  person D_Bester    schedule 22.07.2013
comment
@D_Bester, я написал синглтон, который отвечает за открытие и закрытие экземпляров Excel. У меня никогда не было проблем с утечкой памяти, проблем с производительностью или других форм остаточных проблем. Пока вы гарантируете, что открываемый вами экземпляр является тем, который вы закрываете, я просто рассматриваю это как устранение ошибок в API Excel.   -  person David Colwell    schedule 22.07.2013
comment
@DavidColwell Я написал много приложений, которые используют Excel для выполнения некоторых важных задач, и у меня было много проблем с тем, что процесс Excel не закрывался после выполнения каких-либо действий в Excel.   -  person D_Bester    schedule 22.07.2013
comment
Я обнаружил, что избавление от excel.exe требует трех вещей: установить для всех без исключения ссылок на приложение excel значение null / ничего, GC.Collect(), и приложение должно быть закрыто либо пользователем, либо путем вызова Quit, и если пользователь отменяет закрытие, это не считается. Когда я все это делаю, я получаю лишние excel.exes только при отладке (поскольку остановка выполнения не очистит).   -  person Dave Cousineau    schedule 22.07.2013
comment
Мне никогда не везло с Office Automation (проблемы, которые вы указываете, переносимость и т. Д.) - теперь я просто пишу Word / Excel VBA, чтобы разместить код и запустить программу Word / Excel для выполнения работы. Word, кажется, убирает за собой просто отлично. Я не пробовал это на сервере с большим количеством событий, поэтому он может работать не во всех случаях.   -  person rheitzman    schedule 22.07.2013


Ответы (3)


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

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

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

Даже если ничего из этого не произойдет, вы не можете знать, что может делать будущая версия ОС. То, что работает сегодня, может не работать завтра. Вот почему вы должны ВСЕГДА следовать задокументированным API и руководствам, потому что они обычно будут очень много работать, чтобы поддержать то, что они опубликовали, но обычно не будут очень много работать, чтобы поддержать то, что они специально сказали тебе не делать.

person Erik Funkenbusch    schedule 22.07.2013
comment
Да, пока разработчики программного обеспечения продолжают делать подобные вещи, пользователи всегда будут задаваться вопросом, почему производительность и стабильность их машин со временем ухудшаются, и им приходится переустанавливать операционную систему. - person Cody Gray; 22.07.2013
comment
Здесь все становится немного субъективным, но убивать Excel - это не нарушение закона. Вы должны это сделать, потому что в противном случае вам придется перезагрузить компьютер, когда в вашей системе будет запущено 20 или более невидимых процессов Excel. Это вина Excel, а не пользователя. Завершение работы Excel не приведет к отправке данных телеметрии, и вы не получите проблем с выгрузкой куста реестра, если завершите процесс. ОС гарантирует, что все открытые дескрипторы реестра будут закрыты при завершении процесса, позволяя кусту выгружаться при выходе из системы. Кроме того, это проблема Office, а не ОС. - person Martin Liversage; 22.07.2013
comment
Вы уверены, что это не проблема программиста, что не все открытые ссылки на существующие объекты были удалены, чтобы приложение могло нормально завершиться? - person Lasse V. Karlsen; 22.07.2013
comment
Лассе кое-что понимает. Код действительно пытается выйти из Excel обычным способом, вызывая метод quit. Затем он проверяет, вышел ли он, а если нет, убивает его. Внутри этого оператора if также должно быть утверждение, и при некоторой отладке необходимо выяснить, почему Excel не завершил работу, как вы его еще просили. - person Cody Gray; 22.07.2013
comment
@CodyGray На самом деле мы знаем, почему процесс оболочки Excel не завершается. Microsoft услужливо указала, что неуправляемые ссылки COM учитываются, и как только они все будут выпущены, Excel должен выйти. Тем не менее, потратив часы на отладку и подсчет ссылок, я пришел к выводу, что это просто пустая трата времени. Итак, теперь вопрос в том, почему плохо убивать пустую оболочку процесса после того, как Excel уже завершил работу. Я приглашаю вас написать свой собственный ответ и позволить другим пользователям проголосовать за вас, если им понравится ваш ответ. Я уже знаю, что тебе не нравится мой ответ, но это нормально. Ваш вклад очень полезен. - person D_Bester; 22.07.2013

Когда вы используете автоматизацию для управления приложением Office из другого приложения, вам иногда придется остановить процесс Office, как вы это делаете, чтобы избежать «утечки» невидимых приложений Office. Это досадный результат того, как приложения Office пытаются действовать как приложение конечного пользователя, так и как сервер автоматизации.

Я прибегал к более или менее тому же решению, что и вы, при использовании Word на стороне сервера (не спрашивайте почему). Независимо от того, сколько усилий мы приложим для правильного завершения работы Word, на сервере будет накапливаться все большее количество «невидимых» процессов Word. Единственным хорошим решением было убить те процессы, которые не завершались после получения инструкции о завершении.

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

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

Кроме того, я хотел бы отметить, что «Доктор Ватсон» не будет собирать данные аварийного дампа в случае остановки процесса. Это происходит только в том случае, если процесс неожиданно завершает работу (например, имеет необработанное исключение).

Итог: если вы будете осторожны, убейте Excel, вероятно, лучший способ избежать «утечки» невидимых процессов Excel с течением времени. Альтернатива, позволяющая им работать с использованием все большего количества системных ресурсов до перезапуска системы, нежизнеспособна. Стоимость, если таковая имеется, не должна превышать несколько небольших файлов, оставшихся во временной папке.


В качестве альтернативы автоматизации Office вы можете использовать Open XML SDK для открытия и изменения файлов Office. Первоначально это может быть несколько сложнее, но вы полностью избегаете раскручивания тяжелых приложений Office в процессе.

person Martin Liversage    schedule 22.07.2013
comment
У вас есть ссылка на официальную документацию, которая гарантирует, что с точки зрения операционной системы ничего не произойдет при завершении процесса? Да, ОС пытается навести порядок за вами, но это просто подстраховка, чтобы отловить то, что разработчик мог пропустить. На такое поведение рассчитывать не положено. Я полагаю, что с точки зрения ОС, все работает как надо, но приложение, которое вы убиваете, может не разделять эту точку зрения. - person Cody Gray; 22.07.2013
comment
@CodyGray: Любая подходящая операционная система с процессами очищает все ресурсы, используемые процессом, когда он завершается. Это основное обещание операционной системы. Если что-то просочилось, это происходит в ядре (например, ошибка драйвера или ОС), потому что процесс полностью ушел. - person Martin Liversage; 22.07.2013
comment
Запрос ссылок на документацию с гарантиями фундаментального поведения ОС немного похож на запрос гарантий того, что нажатие педали тормоза в автомобиле остановит его. Найти это в печати, возможно, не так-то просто. Однако я могу порекомендовать прочитать такие книги, как Разработка и реализация операционных систем и Внутреннее устройство Windows. - person Martin Liversage; 22.07.2013
comment
Любая правильная операционная система - это не секвитер. Во-первых, все ОС имеют ошибки, а Windows известна своими ошибками с утечкой ресурсов даже после завершения процессов. Kernel32 и GDI32 часто пропускают дескрипторы, которые никогда не очищаются, потому что это общие процессы по причинам производительности, а ошибки в этих системах приводят к проблемам в общих ресурсах. Во-вторых, я ничего не сказал о Докторе Ватсоне, Windows собирает множество телеметрических данных, не связанных с Watson. - person Erik Funkenbusch; 22.07.2013

По моему опыту, программа выполняет следующие действия при завершении работы:

  1. Освободить все ссылки на память
  2. Удалите все временные или рабочие файлы
  3. Сохраните любые данные о состоянии

По этим причинам крайне важно завершить работу Excel в соответствии с описанием API, используя app.Quit(). В чем этот пример отличается от Нормы, так это в том, что API не освобождает все COM объекты. Это приводит к тому, что шаг 1) не завершен. Невозможно гарантировать эффективное завершение работы приложения во всех случаях, поскольку вы не всегда можете контролировать, какие объекты COM создаются.

Я обнаружил, что лучший способ использовать Excel (среди других офисных программ) - это использовать следующий процесс:

  1. Получить список идентификаторов процессов с именем, содержащим Excel
  2. Открыть Excel
  3. Повторите шаг 1. Используйте это, чтобы определить идентификатор процесса нового экземпляра Excel, который вы создали.
  4. Использовать Excel
  5. Закройте Excel, освободив все созданные вами объекты и завершив работу с Application.Quit().
  6. Убить процесс

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

person David Colwell    schedule 22.07.2013
comment
Я рекомендую вам использовать App.HWND ›GetWindowThreadProcessId (xlHWND, ProcIdXL)› Process.GetProcessById (ProcIdXL) вместо шагов 1 и 3 (как я это делаю, см. Мой вопрос выше) - person D_Bester; 23.07.2013
comment
Также Excel не удаляет временные файлы и не сохраняет данные о состоянии при выходе? Если да, то что на самом деле осталось в процессе? Я подозреваю, что оставшийся процесс Excel на самом деле представляет собой пустую оболочку, которая вообще не содержит Excel. Необходимо удалить только оставшиеся указатели в памяти. - person D_Bester; 23.07.2013
comment
Вы правы, и суть моего аргумента заключается в том, что вы должны вызвать функцию Quit (чтобы Excel мог выполнить всю ее очистку), и все, что осталось, - это пустая оболочка с прикрепленными случайными COM-объектами. , так что можно убить пустую оболочку. По теме: зачем использовать app.HWND? Это надежнее? - person David Colwell; 23.07.2013
comment
App.HWND дает вам правильный дескриптор окна, из которого вы можете получить идентификатор процесса. Таким образом, вы можете быть уверены, что у вас есть правильный процесс, не беспокоясь о полном списке идентификаторов процессов. И это позволяет избежать маловероятного сценария запуска второго экземпляра Excel в тот самый момент, когда вы запускаете Excel до того, как вы получите второй список. Использование App.HWND более надежно. - person D_Bester; 23.07.2013
comment
И, конечно же, я полностью согласен с использованием App.Quit для выхода из Excel. - person D_Bester; 23.07.2013
comment
Я заметил, что процесс задерживается, и последовал совету в самой первой ссылке, предоставленной OP. Это, казалось, надежно закрыло все, и я больше не вижу Excel в списке задач. Кажется, это касается освобождения всех COM-объектов в соответствии с вашей проблемой. - person dudeNumber4; 19.01.2015