I wrote a script when I was relatively new to Powershell to query our servers and write the results to a SharePoint list. The script makes multiple WMI queries and compiles that information. I have found that the WMI connections that are made never seem to close. If I look in my server's security logs, I see the account the script runs under authenticate/logon approximately every two minutes. When I do a netstat -ab on the system the script runs on, I see the connections cycle through ports in the upper ranges. The process running the connections is svchost.exe, connecting to SERVER:epmap. If I continue to watch the connections, I will see it established, then go to time_wait, then cycle back through to established after some time.
My primary question: is there a way to explicitly close a wmi connection after the information has been queried? It seems like the automatic closure of connections is not functioning. I have attempted to use this script on multiple systems, from Server 2008R2 to Windows 7 and receive the same problems. All systems are running powershell 2.0
I have attached the germane code for reference, but at the most basic level, a wmi query is made and the results are written to a hash.
foreach($i.name in $serverHash.GetEnumerator()){
if($serverHash.($i.name).Status -eq "UP"){
$running = @(Get-Job | ? {$_.jobstateinfo.state -eq 'running'})
if($running.count -le $jobLimit){
$i.name
get-wmiobject win32_systemenclosure -computername ($i.name) -asJob
}
else{
Write-verbose "Waiting on system enclosure job queue"
$running | Wait-Job
}
}
}
Write-Verbose "Waiting on jobs"
Wait-Job *
Write-Verbose "Finished Running query"
$jobList = get-job
Write-Verbose "Running loop to update WMI info on hash"
#Run through jobs. If there are errors, update the details in the server's hash table.
#If there aren't errors, continue running other WMI queries.
#region
foreach($i in $jobList){
$status = receive-job -id $i.ID -errorvariable myVar -ErrorAction SilentlyContinue
$name = $i.Location
if($status -eq $null){
if($myVar -match "unavailable"){
Write-Verbose "RPC ERROR: UNAVAILABLE: $name"
$serverHash.$name.set_item("RPCError", "Unavailable")
}
elseif($myVar -match "denied"){
Write-Verbose "ACCESS DENIED: $name"
$serverHash.$name.set_item("Access", "Denied")
}
elseif($myVar -match "namespace"){
Write-Verbose "INVALID NAMESPACE: $name"
$serverHash.$name.set_item("Namespace", "Invalid")
}
$serverHash.$name.set_item("Denied", 1)
}
else{
$system = Get-WmiObject win32_computersystem -ComputerName $name
$operatingSystem = Get-WmiObject win32_operatingsystem -ComputerName $name
$lastBootTime = $operatingSystem.converttodatetime($operatingSystem.lastbootuptime).toshortdatestring()
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $name)
$regKey= $reg.OpenSubKey("SYSTEM\CurrentControlSet\services\Netlogon\Parameters\")
$siteCode = $regKey.GetValue("DynamicSiteName")
$accessError = $Error[0]
if($accessError -match "RemoteBase"){
Write-Verbose "Registry Network path was not found: $name"
$error.clear()
}
$mem = [int]($system.TotalPhysicalMemory/1GB)
if($system.Model -match "^VM"){
$type = "Virtual"
}
else{
$type = "Physical"
}
$serverHash.$name.set_item("Manufacturer", $status.manufacturer)
$serverHash.$name.set_item("Serial", $status.SerialNumber)
$serverHash.$name.set_item("Asset", $status.SMBIOSAssetTag)
$serverHash.$name.set_item("Model", $system.model)
$serverHash.$name.set_item("Processors", $system.NumberOfProcessors)
$serverHash.$name.set_item("Memory", $mem)
$serverHash.$name.set_item("HardwareType", $type)
$serverHash.$name.set_item("Site", $siteCode)
$serverHash.$name.set_item("LastBootupTime", $lastBootTime)
}
}
Remove-Job *