/ / new-object PSObject powoduje błąd wyrażenia o wartości zerowej - powershell, null, expression

PSObject nowego obiektu powoduje błąd wyrażenia o wartości zerowej - powershell, null, expression

Mój skrypt PowerShell:

Param([string]$Computers) #Must supply a comma seperated list of servers
$Threshold = 20 #Only show CPU over this number
$NoP = 20 #Number of processes to list
$NoRS = 4 #Number of result sets
If (! $Computers) {
Write-Host "Connection to server failed - please specify a server name." -ForegroundColor Red
Break
} Else {
$ComputerList = $Computers -Split " "#,[StringSplitOptions]"RemoveEmptyEntries")
}
$Credential = $host.ui.PromptForCredential("Need credentials", "Please enter your user name and password.", "", "NetBiosUserName")
If (! $Credential) {
Write-Host "Authentication failed - please verify your username and password." -ForegroundColor Red
Break
}
$UserName = $Credential.Username
$Password = $Credential.GetNetworkCredential().Password
$CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName
$Domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$UserName,$Password)
If ($Domain.Name -eq $null){
Write-Host "Authentication failed - please verify your username and password." -ForegroundColor Red
Break
}
ForEach ($ComputerName In $ComputerList) {
$LoadPercentage = $Processors.LoadPercentage
If (!$LoadPercentage) {$LoadPercentage = 0}
Write-Host "Server: $ComputerName (CPU load $LoadPercentage%)" -NoNewline
$Processors = Get-WmiObject win32_processor -ComputerName $ComputerName -Credential $Credential
$i = 1
$TopProcess = @()
$PercentComplete = 0
Do{
$PercentComplete = [Math]::Floor($i/$NoRS*100)
Write-Progress -Activity $ComputerName -Status "$PercentComplete% Complete:" -PercentComplete $PercentComplete
$ProcessList = gwmi Win32_PerfFormattedData_PerfProc_Process -ComputerName $ComputerName -Credential $Credential |
Select IDProcess,Name,PercentProcessorTime |
Where {$_.Name -ne "_Total" -and $_.Name -ne "Idle"} |
Sort PercentProcessorTime -Descending |
Select -First $NoP
ForEach ($Process In $ProcessList) {
$row = New-Object PSObject -Property @{
Id = $Process.IDProcess
Name = $Process.Name
User = (gwmi Win32_Process -ComputerName $ComputerName -Credential $Credential | Where {$_.ProcessId -eq $Process.IDProcess}).GetOwner().User
CPU = $Process.PercentProcessorTime/$Processors.NumberOfLogicalProcessors -f {P}
Description = (gwmi Win32_Process -ComputerName $ComputerName -Credential $Credential | Where {$_.ProcessId -eq $Process.IDProcess}).Description
}
$TopProcess += $row
}
$i++
} While ($i -lt $NoRS + 1)
Write-Progress -Activity $ComputerName -Completed
$Group = $TopProcess | Where {$_.CPU -gt $Threshold} | Group "ID" | Where Count -eq $NoRS
If (!$Group) {
Write-Host " has no processes persistently above $Threshold percent CPU usage."
} Else {
$Processes = @()
ForEach ($Groupee In $Group) {
$Ungroup = $Groupee | Select -ExpandProperty Group
$CPU = 0
ForEach ($ugr in $Ungroup) {
$CPU += $ugr.CPU
}
$row = new-object PSObject -Property @{
Id = $Ungroup.Id | Select -First 1
Name = $Ungroup.Name | Select -First 1
CPU = $CPU/$NoRS
User = $Ungroup.User | Select -First 1
Description = $Ungroup.Description | Select -First 1
}
$Processes += $row
}
$Processes | Format-Table @{Expression={$_.User};Label="User Name";width=25},@{Expression={$_.CPU};Label="CPU";width=5},@{Expression={$_.Id};Label="ID";width=8},@{Expression={$_.Description};Label="Description";width=48}
}
}

sporadycznie wyświetla następujący błąd:

Nie można wywołać metody dla wyrażenia o wartości zerowej. W C: UsersJasons1CPUusage.ps1: 41 znak: 4

  • $ row = nowy obiekt PSObject -Property @ {

  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    • CategoryInfo: InvalidOperation: (:) [], RuntimeException
    • FullyQualifiedErrorId: InvokeMethodOnNull

którego nie rozumiem, ponieważ jest w pętli i powinien albo działać, albo zostać pominięty, ponieważ istnieje test na wartość NULL.

Odpowiedzi:

2 dla odpowiedzi № 1

Jestem pewien, że Twoje problemy wynikają z tego wiersza:

User = (gwmi Win32_Process -ComputerName $ComputerName -Credential $Credential | Where {$_.ProcessId -eq $Process.IDProcess}).GetOwner().User

W szczególności od .GetOwner(). Twoja klauzula where nie może znajdować procesu dopasowywania dla tego elementu, gdy jest on w pętli. Zdaję sobie sprawę, że nie upłynęło wiele czasu, ale zapytania WMI nie są najszybszymi rzeczami.

To, co się dzieje, jest prawdopodobnie wynikiem wcześniejszego zapytania $ProcessList = gwmi Win32_PerfFormattedData_PerfProc_Process i później, kiedy używasz gwmi Win32_Process lista procesów uległa zmianie. Musisz to również uwzględnić. Czas minął, a wątki nie żyją wiecznie.

$queryResult = gwmi Win32_Process -ComputerName $ComputerName -Credential $Credential | Where {$_.ProcessId -eq $Process.IDProcess}
$owner = if($queryResult){$queryResult.GetOwner().User}else{"Process DNE"}
#...

User = $owner

Niezbyt ładne, ale uwzględnia potencjał zerowego zwrotu z zapytania wmi.