首页 > 解决方案 > 在 Powershell 脚本中处理 COM 对象

问题描述

我有一个运行 Powershell 脚本的计划任务。此 Powershell 脚本发送 HTTP 请求并搜索返回的 HTML。由于这个脚本,我留下了一堆没有关闭的 dllhost 进程。如果我理解正确,这是 COM 对象的结果。

与 COM 对象相关的唯一变量是:

$specifiedDiv = $request.ParsedHtml.Body.getElementsByTagName('div') |
    Where-Object{$_.getAttributeNode('class').Value -eq 'results'}

当我运行时$specifiedDiv.GetType(),我得到这个结果:

IsPublic IsSerial Name                                     BaseType                                                                                                                                                              
-------- -------- ----                                     --------                                                                                                                                                              
True     False    __ComObject                              System.MarshalByRefObject 

我的问题是如何关闭此对象或阻止脚本创建 dllhost 进程?

编辑:

    Function garbageCollect ([object]$ref){

            ([System.Runtime.Interopservices.Marshal]::ReleaseComObject([System.__ComObject]$ref) -gt 0)
            [System.GC]::Collect()
            [System.GC]::WaitForPendingFinalizers()
        }
$parsedHtml = $request.ParsedHtml
$body = $parsedHtml.Body
$divs = $body.getElementsByTagName('div')


$classAttribute = $divs | Where-Object{$_.getAttributeNode('class').Value -eq 'results-found'}

        Remove-Variable -Name classAttribute
        Remove-Variable -Name parsedHtml
        Remove-Variable -Name body
        Remove-Variable -Name divs

        garbageCollect($parsedHtml)
        garbageCollect($body)

        foreach($div in $divs)
        {
            garbageCollect($div)
        }
        foreach($thing in $classAttribute)
        {
            garbageCollect($div)
        }

我尝试了上述方法,但仍然得到 dllhost 进程。

标签: powershellcomhttprequestdllhost

解决方案


嗯,它比这更复杂。有

[System.InteropServices.Marshal]::ReleaseComobject($specifiedDiv)

这可能行得通……但是,.NET 使用 COM 对象的方式,您可能会在各处创建一堆中间 COM 对象。如$request、$request.ParsedHtml、$request.ParsedHtml.Body。然后可能会在调用 $_.getAttributeNode('class') 时创建一大堆其他 COM 对象。

$parsedHtml = $request.ParsedHtml
$body = $parsedHtml.Body
$divs = $body.getElementsByTagName('div')

foreach ($div in $divs)
{
   $attrNode = $div.getAttributeNode('class')

   if ($attrNode.Value -eq 'results')
   {
      $specificDiv = $attrNode
      break
   }
   else
   {
      [System.Runtime.Interopservices.Marshal]::ReleaseComObject($div)
   }
}

[System.Runtime.Interopservices.Marshal]::ReleaseComObject($divs)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($body)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($parsedHtml)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($request)
### what is this ??? [System.Runtime.Interopservices.Marshal]::ReleaseComObject($requestHome)


#### Do something with $specificDiv if you want...however, you might create more COM objects...


[System.Runtime.Interopservices.Marshal]::ReleaseComObject($specifiedDiv)

推荐阅读