Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.6k views
in Technique[技术] by (71.8m points)

powershell - Cannot remove variable because it has been optimized and is not removable - releasing a COM object

At the end of my script I use 'ie' | ForEach-Object {Remove-Variable $_ -Force}. It works fine in PS 2 (Windows 7) but PS 5 (Windows 10) throws an error:

Cannot remove variable ie because the variable has been optimized and is not removable. Try using the Remove-Variable cmdlet (without any aliases), or dot-sourcing the command that you are using to remove the variable.

How can I make it play nice with PS 5; or should I just use Remove-Variable 'ie' -Force?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The recommended way to remove COM objects is to call the ReleaseComObject method, passing the object reference ($ie) to the instance of your COM object.

Here is more detailed explanation and sample code from a Windows PowerShell Tip of the Week that shows how to get rid of COM objects:

Whenever you call a COM object from the common language runtime (which happens to be the very thing you do when you call a COM object from Windows PowerShell), that COM object is wrapped in a “runtime callable wrapper,” and a reference count is incremented; that reference count helps the CLR (common language runtime) keep track of which COM objects are running, as well as how many COM objects are running. When you start Excel from within Windows PowerShell, Excel gets packaged up in a runtime callable wrapper, and the reference count is incremented to 1.

That’s fine, except for one thing: when you call the Quit method and terminate Excel, the CLR’s reference count does not get decremented (that is, it doesn’t get reset back to 0). And because the reference count is not 0, the CLR maintains its hold on the COM object: among other things, that means that our object reference ($x) is still valid and that the Excel.exe process continues to run. And that’s definitely not a good thing; after all, if we wanted Excel to keep running we probably wouldn’t have called the Quit method in the first place. ...

... calling the ReleaseComObject method [with] our instance of Excel ... decrements the reference count for the object in question. In this case, that means it’s going to change the reference count for our instance of Excel from 1 to 0. And that is a good thing: once the reference count reaches 0 the CLR releases its hold on the object and the process terminates. (And this time it really does terminate.)

$x = New-Object -com Excel.Application
$x.Visible = $True
Start-Sleep 5
$x.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($x)
Remove-Variable x

The message "Cannot remove variable ie because the variable has been optimized and is not removable." you get, most likely means you have tried to access (inspect, watch, or otherwise access) a variable which has been already removed by the optimizer.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...