Удаление COM-объектов в сценарии Powershell
У меня есть запланированная задача, которая запускает сценарий 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.
1 ответ
Что ж, это сложнее. Там есть
[System.InteropServices.Marshal]::ReleaseComobject($specifiedDiv)
Это может сработать... однако, как.NET работает с COM-объектами, у вас может быть куча промежуточных COM-объектов, создаваемых повсюду. Например, $request, $request.ParsedHtml, $request.ParsedHtml.Body. Тогда может быть целая куча других COM-объектов, созданных при вызове $_. GetAttributeNode('class').
$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)