Не удается остановить все процессы Excel при закрытии через Powershell - PullRequest
2 голосов
/ 29 марта 2019

С помощью этого кода я открываю Excel (с visible = false, поэтому пользователь не может его видеть), записываю в книгу, а затем либо открываю Excel (делая его видимым) после завершения сценария, либо полностью закрываю его без сохранения.Когда я сохраняю Excel, оставляю его открытым, завершаю скрипт, а затем вручную закрываю Excel, в диспетчере задач нет фоновых процессов.Однако когда я закрываю Excel со скриптом, он остается в диспетчере задач.

Вот как я запускаю Excel:

    $script:excel = new-object -ComObject excel.application # create excel object
    $excel.visible = $false # hide excel window
    $script:workbook = $excel.Workbooks.Add() # add excel file
    $script:ws1 = $workbook.Worksheets.Item(1) # create new sheet

Вот как я его закрываю:

        [gc]::Collect()
        [gc]::WaitForPendingFinalizers()
        if ($script:closeOnX) {
            #only do this if not keeping excel open
            Write-Host "Closing Excel"
            $excel.Quit()
        }
        [System.Runtime.InteropServices.Marshal]::ReleaseComObject($excel)

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

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

Когда я заканчиваю скрипт, сохраняю и открываю Excel, я хочу, чтобы все процессы исчезли, когда пользователь вручную закрывает Excel.(Это работает)

1 Ответ

1 голос
/ 29 марта 2019

Начиная с Windows PowerShell v5.1 / PowerShell Core 6.2., Есть ошибка, препятствующая освобождению ссылок на COM-объекты ; см. этот выпуск GitHub .

Обходной путь предназначен для явного задания переменных, ссылающихся на COM-объекты, на $null или для их удаления с помощью Remove-Variable:

$script:excel = new-object -ComObject excel.application # create excel object
$script:excel.visible = $false # hide excel window
$script:workbook = $excel.Workbooks.Add() # add excel file
$script:ws1 = $workbook.Worksheets.Item(1) # create new sheet

# ...

$script.excel.Quit()

# Workaround to ensure release.
$script:excel = $script:workbook = $script:ws1 = $null

# Calling the garbage collector isn't *necessary*,
# but may *speed up* the release.
# Also calling [GC]::WaitForPendingFinalizers() is pointless, however,
# because the CLR-managed RCWs (Runtime-Callable Wrappers for COM objects)
# do not guarantee deterministic release of the underlying COM objects.
[GC]::Collect()
...