最近有一组关于通过PowerShell操作Internet Explorer的问题。它们都包含了启动IE对象的代码,如$ie=new-object -comobject InternetExplorer.Application
。问题是,使用正确的方法关闭 IE,也就是调用 $ie.quit()
并没有起作用。首先,如果该IE窗口有不止一个打开的标签页,那么整个IE不会退出,只有对应COM对象的标签页被关闭。其次,如果该IE窗口只有一个标签页,那么窗口会关闭,但是进程仍然在运行。
PS > get-process iexplore
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
352 31 7724 24968 142 0,58 3236 iexplore
228 24 22800 15384 156 0,19 3432 iexplore
我尝试研究如何关闭通过New-Object -ComObject
启动的进程的方法,并找到了这个链接:如何摆脱COM对象。该COM对象的示例为Excel.Application
,它确实表现出预期的行为——调用quit()
会关闭窗口,如果$ex
是已创建的COM对象,则执行[System.Runtime.Interopservices.Marshal]::ReleaseComObject($ex)
可以停止Excel进程。但这不适用于Internet Explorer。
我还发现了这个问题:如何获取正在运行的IE的现有COM对象,其中提供了通过打开窗口列表连接到IE的代码,并且在从其他地方启动IE的情况下可以正常工作,但如果通过PowerShell创建COM对象,则无法完全停止IE的进程,如果修改为这样:
$shellapp = New-Object -ComObject "Shell.Application"
$ShellWindows = $shellapp.Windows()
for ($i = 0; $i -lt $ShellWindows.Count; $i++)
{
if ($ShellWindows.Item($i).FullName -like "*iexplore.exe")
{
$ie = $ShellWindows.Item($i)
$ie.quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($ie)
}
}
如果在PowerShell之外启动IE,则进程会停止,但是如果在PowerShell中启动IE,则会保留两个进程,此代码报告找不到任何IE窗口以访问COM对象,因此IE进程无法被(尚未)停止。
那么,如何访问明显的无主窗口IE进程并优雅地停止它们?我知道Get-Process iexplore | Stop-Process
,但这将停止所有IE,而不仅仅是由脚本启动的IE,如果脚本作为管理员或SYSTEM
在远程桌面服务器上运行,则所有人的IE都将停止。
环境: 操作系统Windows 7 x64,PowerShell 4(安装在PS版本2以上),IE11版本11.0.9600.17691(自动更新)。 IE设置为“打开主页”以启动,因此至少始终打开一个选项卡。
[Runtime.Interopservices.Marshal] :: ReleaseComObject()
时,它返回一个非零值 - 这显然表明系统中还有更多链接到该COM对象的链接。在我的情况下,启动了三个进程,而不是两个。这可能因IE版本和操作系统版本而异,因此我将在其他PC上再次检查。到目前为止,看起来像是IE11引入的错误或.NET 4.5中的错误,如果此问题也会在Win8.1和IE11(现在无法访问)的PC上显示。 - VesperStart-Process
作为启动IE的手段,一旦我掌握了该进程创建的COM对象,简单的quit()
就可以起作用。但是,如果我按照我在问题中描述的那样做,它就不会退出。 - Vesperquit()
,我的PC不能关闭IE是不正常的。到目前为止,我测试过的其他PC(三台,一台Server 2012,一台安装了IE8的XP和一台8.1)都会在我告诉它退出时停止IE的进程。因此,我认为这才是正确的方式,而我在这里遇到的是某种错误,我将尝试更多地查找导致该错误的原因。 - Vesper