测试 Excel 是否已完成其启动/关闭序列

Test if Excel has finished its startup / shutdown sequence

我正在使用 PowerShell 通过 COM 通过 PowerShell 脚本自动执行某些 excel 任务,如下所示:

$xl = new-object -ComObject Excel.Application
sleep 5
DO THINGS...
$xl.quit()
sleep 5
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl)
[GC]::collect()

我的问题是,如果我省略对 sleep 的第一次调用,Excel 将无法执行需要加载项的任务,而对 $xl.quit() 的调用不起作用,并且进程无法退出,如下所示:

PS > Get-Process EXCEL

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    784     104   104008     109380   944     3.21   5996 EXCEL

同样,如果我省略对 sleep 的第二次调用,excel 就没有时间完成关闭,最终会出现一个对话框,显示 "Microsoft Excel has stopped working..." 和下次 Excel 启动时,另一个对话框显示 "Microsoft Excel failed to shut down properly, Start in safe mode?"

function XLtest {
    $xl = new-object -ComObject Excel.Application
    $xl.quit()
    $null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl)
    [GC]::collect()
}

for($i=0;$i -lt 10; $i++){ XLtest } # generates multiple errors

显然这些是我想避免的问题,但是调用 sleep 5 的启发式解决方案在某些情况下仍然会失败。有什么方法可以检测 excel 何时完成其启动序列并准备好发出命令(特别是 xl.quit() )以及关闭序列何时完成(即何时可以调用[System....Marshal]::ReleaseComObject($xl)?

如果没有像 DO THINGS... 这样的插件,您的确切环境和情况是不可能重现的,Excel Application object 的成员应该能够利用它来了解应用程序状态。

_Application.CalculationState property 似乎是一个可能的候选人。如果强制进行完全重新计算,然后处理 Do While...: DoEvents: Loop,伪计时器可能会暂停 powershell 脚本,而 Application.CalculationStatexlDone 不一样 Internet.Explorer等待对象直到它完成接收其网页。

$xl = new-object -ComObject Excel.Application
$xl.Calculate
do while $xl.CalculationState <> xlDone: $xl.DoEvents: Loop
$xl.quit()
... (do more things?)

如果您在关闭(并随后退出)之前保存,也可以使用 _Application.CalculateBeforeSave property 强制重新计算。

另一个不错的候选者是更简单的 _Application.Ready property

$xl = new-object -ComObject Excel.Application
do while not $xl.ready: $xl.DoEvents: Loop
$xl.quit()

参见 Application Members (Excel) for a full list of potential properties where a 'state' can be determined. More information at Developer’s Guide to the Excel 2010 Application Object