通过Powershell关闭时无法停止所有Excel进程

时间:2019-03-29 18:04:12

标签: excel powershell user-interface com rcw

使用此代码,我将打开excel(可见= 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 个答案:

答案 0 :(得分:1)

从Windows PowerShell v5.1 / PowerShell Core 6.2开始,存在一个阻止COM对象引用被释放的错误;参见this GitHub issue

解决方法是明确设置将引用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()