将WorkSheet.UsedRange分配给PowerShell Excel自动化中的variables时性能会受到影响

我是新来的COM对象的工作,我已经读了我可以了解这个问题,但我似乎无法弄清楚这种行为。 我怀疑在封面下有什么明显的东西,我只是不明白。 我使用LogParser自动处理IIS日志,并在Excel中构build报告。 我开始使用我写的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时它挂起来了。 我不知道为什么它只会在大型工作表中挂起。 Large由25K行和15-20列定义,对于Excel可以处理的数量并不大。 这是Release-Reffunction:

 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 } } } 

在逐步完成这个function的时候,我也注意到它也会落后于if($ref -ne $null) 。 我构build了代码块和基于这个post的函数,其中声明了“不要使用2个点与COM对象”,并且展示了如何正确清理Mike Rosenblom的回应之后的Excel进程。 我原来在自动化结束时遗留了Excel进程的问题,并尽我所能地遵循这一原则。 我最终得到Excel正常closures,但执行一些报告需要20-40分钟。

我终于移动到下面的代码块代替之前的:

 $lastCell = $WorkSheet.UsedRange.SpecialCells($xlCellTypeLastCell) if($Axis -eq 'Row'){$tmpLast = $lastCell.Row} if($Axis -eq 'Column'){$tmpLast = $lastCell.Column} 

我现在正在违反2点原则,但是这样做可以消除挂起的电话,现在报告只需几分钟。 Excel仍然closures,但不像以前那样直接。 我担心Excel现在可能会偶尔出现,但是性能改进目前是值得的。

我的问题归结为:

  1. 我是否应该关注那个基于违反该代码段中的2点原理的Excel将来closures?
  2. 而且,什么解释了原始代码上的“大型”工作表的性能?

我不会想到这将是缓慢的Release-Ref函数的调用,但它里面的东西,因为我不太熟悉垃圾收集过程。