Performance 在PowerShell Excel Automation中将sheet.UsedRange分配给变量时出现性能问题

Performance 在PowerShell Excel Automation中将sheet.UsedRange分配给变量时出现性能问题,performance,excel,powershell,interop,com-interop,Performance,Excel,Powershell,Interop,Com Interop,我对使用COM对象还不熟悉,我已经阅读了一些我能理解的东西,但是我似乎无法理解这种行为。我怀疑有什么明显的事情在幕后进行,我只是不明白。我正在使用LogParser自动处理IIS日志,并在Excel中生成报告。我从编写PowerShell模块中的以下代码块开始,以获得使用的最后一列: $used = $WorkSheet.usedRange $lastCell = $used.SpecialCells($xlCellTypeLastCell) if($Axis -eq 'Row'){$tmpLa

我对使用COM对象还不熟悉,我已经阅读了一些我能理解的东西,但是我似乎无法理解这种行为。我怀疑有什么明显的事情在幕后进行,我只是不明白。我正在使用LogParser自动处理IIS日志,并在Excel中生成报告。我从编写PowerShell模块中的以下代码块开始,以获得使用的最后一列:

$used = $WorkSheet.usedRange
$lastCell = $used.SpecialCells($xlCellTypeLastCell)
if($Axis -eq 'Row'){$tmpLast = $lastCell.Row}
if($Axis -eq 'Column'){$tmpLast = $lastCell.Column}
Release-Ref $used
$WorkSheet是有效的工作表对象。这个代码块在小型工作表上工作得很好,但是随着工作表大小的增加,执行时间会越来越长。如果床单太大的话,它就会全部挂起来。此外,它会开始挂起我试图使用的其他应用程序,而我只是等待它完成,然后才能使用我的计算机。这不是一个资源问题,因为我在一个有24GB内存的i7上运行它。当我浏览PowerShell ISE(2.0)中的代码时,我发现当我进入
Release Ref$used
时,它是挂起的。我不知道为什么它只会挂在大工作表的那一行。“大”由约25K行和15-20列定义,对于Excel来说,它并没有那么大。以下是Release Ref函数:

function Release-Ref{
[CmdletBinding(DefaultParameterSetName='Single')]
param(
    [Parameter(Mandatory=$true,Position=0,ParameterSetName='Single')]
    [System.__ComObject]$ref,

    [Parameter(Mandatory=$true,Position=0,ParameterSetName='Array')]
    [System.__ComObject[]]$refs,

    [Switch]$Final
)
if($Final){
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()
}
if($PSCmdlet.ParameterSetName -eq 'Array'){
    foreach($ref in $refs){
        if($ref -ne $null){
            [System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($ref) `
                | Out-Null
        }
    }
}else{
    if($ref -ne $null){
        [System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($ref) `
            | Out-Null
    }
}
}
在单步执行此函数时,我还注意到如果($ref-ne$null),它也会滞后于
。我构建了有问题的代码块和函数,函数的基础是“永远不要对COM对象使用2个点”,并在Mike Rosenblom的回答之后演示了如何正确清理Excel过程。我最初对自动化结束时遗留下来的Excel过程有问题,并尽我所能遵循这一原则。我最终让Excel正常结束,但一些报告的执行需要20-40分钟

最后,我转到以下代码块,以替换前面的代码块:

$lastCell = $WorkSheet.UsedRange.SpecialCells($xlCellTypeLastCell)
if($Axis -eq 'Row'){$tmpLast = $lastCell.Row}
if($Axis -eq 'Column'){$tmpLast = $lastCell.Column}
我现在违反了2点原则,但这删除了挂起的呼叫,现在报告在几分钟内运行。Excel仍在关闭,但不像以前那样立即关闭。我担心Excel现在可能会偶尔出现,但目前性能的提高是值得的

我的问题归结为:

  • 我是否应该担心Excel将来会因为违反该部分代码中的2点原则而无法关闭
  • 那么,是什么解释了原始代码上“大型”工作表的性能下降呢 我没想到调用Release-Ref函数会很慢,但是里面有些东西,因为我对垃圾收集过程不太熟悉