Вопрос:
Независимо от того, что я пытаюсь, Excel 2013 продолжает работать в фоновом режиме на Windows 10 независимо от того, какие команды я бросаю в конце моего сценария PowerShell. Я попытался добавить все предложения, которые я нашел в конец моего скрипта, и единственный объект Excel, который я открываю, продолжает оставаться открытым. Вот что я имею в конце моего сценария. Любые другие предложения?
## Quit Excel and Terminate Excel Application process: $xlsxwb.quit $xlsxobj.Quit [System.Runtime.Interopservices.Marshal]::ReleaseComObject($xlsxobj) [System.Runtime.Interopservices.Marshal]::ReleaseComObject($xlsxwb) [System.Runtime.Interopservices.Marshal]::ReleaseComObject($xlsxSh1) Start-Sleep 1 ‘Excel processes: {0}’ -f @(Get-Process excel -ea 0).Count Лучший ответ:
Я столкнулся с той же проблемой и безуспешно пробовал различные решения. Я стал ближе, когда начал выпускать все COM-объекты, которые я сохранил в качестве переменных, а не только для рабочей книги, рабочего листа и приложения Excel.
Например, возьмите следующий пример кода:
$Excel = New-Object -ComObject Excel.Application $Excel.Visible = $False $Workbook = $Excel.Workbooks.Open(«C:Temptest.xlsx») $Worksheet = $Workbook.Worksheets.Item(1) $UsedRange = $Worksheet.UsedRange $Range = $Worksheet.Range(«A1:B10») $Workbook.Close() $Excel.Quit() [void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($Range) [void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($UsedRange) [void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($Worksheet) [void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($Workbook) [void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel) [GC]::Collect()
Если вы выберете только один из операторов ReleaseComObject, процесс Excel останется открытым. В моем коде я сначала выпускаю все, например, диапазоны, таблицы и т.д., А затем создаю рабочий лист, книгу и, наконец, приложение Excel. Тогда, поскольку это только работало, как 90% времени, я добавил команду сбора мусора в конце и, наконец, получил решение, которое, кажется, работает каждый раз, не убивая процесс.
Примечание. Моя система – Windows 8.1 с PowerShell v5 и Office 2013.
Ответ №1
Вот простой пример ниже. Вероятно, для этого потребуется дополнительный код для более сложных процедур.
function _FullQuit { while ( $this.Workbooks.Count -gt 0 ) { $this.Workbooks.Item(1).Close() } $this.Quit() [System.Runtime.InteropServices.Marshal]::ReleaseComObject($this) [System.GC]::Collect() [System.GC]::WaitForPendingFinalizers() } function New-Excel { $object = New-Object -ComObject «Excel.Application» $object | Add-Member -MemberType ScriptMethod -Name FullQuit -Value {_FullQuit} $object } $xl = New-Excel $wb1 = $xl.Workbooks.Open(«C:Data1.csv») $wb2 = $xl.Workbooks.Open(«C:Data2.csv») $xl.FullQuit() Ответ №2
Вышеупомянутые решения не сработали для меня, в последовательности, в которой я нуждался, последний шаг был .saveas(file.xlsx) что означало, что в оставшемся несохраненном документе по-прежнему появился интерфейс gui, требующий взаимодействия пользователя, чтобы сохранить/не сохранять/отменять.
Я закончил со следующим, что, по общему признанию, грубо, но работал на меня.
В начале скрипта:
$existingExcel = @() Get-Process Excel | % {$existingExcel += $_.ID } function Stop-Excel { Get-process EXCEL | % {IF($_.ID -notmatch $existingExcel){Stop-Process -ID $_.ID}} }
и в конце скрипта
Stop-Excel
Это имеет то преимущество, что полностью уничтожает любые затяжные процессы excel, не прерывая никаких других процессов live excel, которые могут использоваться пользователями, которые работают, с этим скриптом.
Недостатки заключаются в том, что при следующей загрузке вы получаете разбитый диалог восстановления документа Excel.
Ответ №3
Альтернативный ответ:
Я понимаю, что мой ответ опоздал, но все же рассмотрим следующий подход, чтобы сделать это.
-
В начале, получите PID любого/всех экземпляров excel.exe, используя команду:
tasklist /FI «imagename eq excel.exe»
-
Запустите ту часть скрипта, которая генерирует его экземпляр excel.exe. Используйте команду на шаге 1, чтобы идентифицировать и сохранить PID вновь созданного экземпляра excel.exe (скажем, wxyz), это будет отличаться от уже существующих PID, сохраненных на шаге 1.
-
В конце скрипта закройте конкретный экземпляр (с PID, сохраненным на шаге 2), используя команду:
TASKKILL /f /PID wxyz
где wxyz – это 4-значный PID, сохраненный на шаге 2.