Ves*_*per 8 com powershell internet-explorer
有一组最近被问到的关于通过PowerShell使用Internet Explorer做一些事情的问题.所有这些都包含从PowerShell作为对象启动IE的代码$ie=new-object -comobject InternetExplorer.Application.问题是,关闭由调用组成的IE 的正确方法$ie.quit()不起作用 - 首先,如果IE碰巧有多个单独的打开选项卡,IE不会作为一个整体退出,只有对应的选项卡COM对象关闭,其次,如果它只有一个选项卡,则窗口关闭但进程仍然存在.
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
Run Code Online (Sandbox Code Playgroud)
我试图研究如何关闭一个进程启动的方法New-Object -ComObject,并找到了:如何摆脱COMObject.COMObject的示例Excel.Application实际上表现如预期 - 调用quit()使窗口关闭,并且执行[System.Runtime.Interopservices.Marshal]::ReleaseComObject($ex)if $ex是创建的COMObject会停止Excel进程.但是Internet Explorer不是这种情况.
我还发现了这个问题:如何获取正在运行的IE的现有COM对象,它提供了通过打开的窗口列表连接到IE的代码,并且工作到从其他地方启动的IE的程度,但是如果COM对象是通过PowerShell创建的,此脚本无法完全停止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)
}
}
Run Code Online (Sandbox Code Playgroud)
如果在PowerShell之外启动IE,则会停止进程,但是如果在PowerShell中启动IE,则会保留两个进程,并且此代码报告找不到IE窗口来访问COM对象,因此IE进程(还)无法进行要停下来
那么,如何到达显然孤立的无窗口IE进程并优雅地阻止它们?我知道Get-Process iexplore | Stop-Process,但是这将阻止任何和所有IE,而不仅仅是脚本启动的IE,如果脚本以管理员或SYSTEM远程桌面服务器的形式运行,那么每个人的IE都将被停止.
环境:OS Windows 7 x64,PowerShell 4(安装在PS版本2上方),IE11版本11.0.9600.17691(自动更新).IE在启动时设置为"打开主页",因此至少有一个选项卡始终打开.
简单地调用该Quit()方法通常应该足以优雅地终止Internet Explorer进程,无论它们是通过运行iexplore.exe还是通过在PowerShell中实例化COM对象来创建的.
示范:
PS C:\> $env:PROCESSOR_ARCHITECTURE
AMD64
PS C:\> (Get-WmiObject -Class Win32_OperatingSystem).Caption
Microsoft Windows 8.1 Enterprise
PS C:\> Get-Process | ? { $_.ProcessName -eq 'iexplore' }
PS C:\> $ie = New-Object -COM 'InternetExplorer.Application'
PS C:\> Get-Process | ? { $_.ProcessName -eq 'iexplore' }
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
352 20 4244 14164 176 0.05 3460 iexplore
407 32 6428 23316 182 0.23 5356 iexplore
PS C:\> $ie.Quit()
PS C:\> Get-Process | ? { $_.ProcessName -eq 'iexplore' }
PS C:\> _
如果您有孤立的Internet Explorer进程,您没有句柄,您可以像这样循环:
(New-Object -COM 'Shell.Application').Windows() | Where-Object {
$_.Name -like '*Internet Explorer*'
} | ForEach-Object {
$_.Quit()
}
Run Code Online (Sandbox Code Playgroud)
为了完全安全起见,您可以在调用后释放COM对象Quit(),然后等待垃圾收集器清理:
(New-Object -COM 'Shell.Application').Windows() | Where-Object {
$_.Name -like '*Internet Explorer*'
} | ForEach-Object {
$_.Quit()
[Runtime.Interopservices.Marshal]::ReleaseComObject($_)
}
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
Run Code Online (Sandbox Code Playgroud)