Quantcast
Channel: The Official Scripting Guys Forum! forum
Viewing all articles
Browse latest Browse all 15028

Powershell closing Excel objects with ReleaseComObject leaves dangling posh variables

$
0
0

Per this link:

http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/81dcbbd7-f6cc-47ec-8537-db23e5ae5e2f

the correct way to avoid Excel zombies is to release all ComObjects in the powershell environment / script by invoking:

while ([System.Runtime.InteropServices.Marshal]::ReleaseComObject($comobject)) {}
}

on each posh variable holding a reference to a COM object, and to do so in "reverse" order (suitably defined).

"Correct" means specifically"leaves no invisible lurking Excel apps behind".

The recipe works for me when I invoke my scripts as (say):

$ ./script.ps1

But when I invoke the script as:

. ./script.ps1

and then list posh variables:

$ ls variable:

posh throws an error when it encounters the first variable that (previously) held a ComObject reference:

ls : COM object that has been separated from its underlying RCW cannot be used.
At line:1 char:1+ ls variable:+ ~~~~~~~~~~~~~~~~~~+ CategoryInfo          : NotSpecified: (:) [Get-ChildItem], InvalidComObjectException+ FullyQualifiedErrorId : System.Runtime.InteropServices.InvalidComObjectException,Microsoft.PowerShell.Commands.GetChildItemCommand

I tried rv'ing the posh variables, but when I do so prior to the ReleaseComObject, I no longer have a handle to the Com Object; alternatively when I rv the posh variable after ReleaseComObject, posh throws the same error as above.

How to release both the Com Object and the posh variable in the base posh environment (ie . ./script) while avoiding Excel zombies?

Code excerpts below:

function release($foo) { while ([System.Runtime.InteropServices.Marshal]::ReleaseComObject($foo)) {} } function killExcel() { $xl.displayalerts = $false for ($i=1; $i -lt $wss.count; $i++) { $wss.Item(1).Delete() } release $wss $wb.close($false, $false, $false) release $wb } function quit() { killExcel $xl.Quit() release $xl [gc]::collect() [gc]::WaitForPendingFinalizers() exit } ...

// read xml file, define xmltitle variable

...

// define $count = # workbook pages ... $xl = new-object -comobject Excel.Application $xl.Visible = $True $xl.DefaultFilePath = (Get-Location).ToString() + "SpreadSheets.d\" $xl.DefaultFilePath.ToString() %{$title = $xmltitle.split()} $title[1] = $title[1] -replace "[.]","dot" $filename=$xl.DefaultFilePath.ToString() + $title[1] + "_" + $title[2] + ".xlsx" $filename.ToString() $xl.sheetsInNewWorkbook = $count $wb = $xl.Workbooks.Add() $wss = $wb.worksheets $sstoc = $wss.Item(1) $sstoc.name = "Table of Contents" $sscells = $sstoc.cells $sscells.item(1,1) = $xmltoc.index release $sscells release $sstoc try { $wb.saveas($filename, $xlFileFormat::xlWorkbookDefault) } catch [system.exception] { // ignore it } quit

TIA for the help.

FWIW, I'm running Win7 and Office 2010 in a Workstation 8 VM.

Jim Snyder


Viewing all articles
Browse latest Browse all 15028

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>