Powershell 新对象PSObject导致空值表达式错误

Powershell 新对象PSObject导致空值表达式错误,powershell,null,expression,Powershell,Null,Expression,我的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 "Conn

我的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}
    }
}
间歇性地出现以下错误:

不能对空值表达式调用方法。在C:\Users\Jasons1\CPUusage.ps1:41 char:4

  • $row=新对象PSObject-属性@{

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

    • CategoryInfo:InvalidOperation:(:)[],运行时异常
    • FullyQualifiedErrorId:InvokeMethodOnFull

我无法理解,因为它在一个循环中,应该工作或被跳过,因为有一个空测试。

非常确定您的问题来自这一行:

特别是在
.GetOwner()
中。当项目在循环中时,where子句不能为该项目找到匹配的进程。我知道时间不多,但WMI查询不是最快的

发生的情况很可能是前面在
$ProcessList=gwmi Win32_performatteddata_PerfProc_process
中查询的某个进程的结果,然后当您使用
gwmi Win32_process
时,进程列表发生了更改。您也需要对此进行说明。时间已经过去,线程不会永远存在

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

User = $owner

虽然不是很漂亮,但考虑到wmi查询可能返回空值。

非常确定您的问题源自以下几行:

特别是在
.GetOwner()
中。当项目在循环中时,where子句不能为该项目找到匹配的进程。我知道时间不多,但WMI查询不是最快的

发生的情况很可能是前面在
$ProcessList=gwmi Win32_performatteddata_PerfProc_process
中查询的某个进程的结果,然后当您使用
gwmi Win32_process
时,进程列表发生了更改。您也需要对此进行说明。时间已经过去,线程不会永远存在

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

User = $owner

虽然不是很漂亮,但说明了wmi查询可能返回空值。

失败的一行很可能是“User=”(gwmi Win32_进程-ComputerName$ComputerName….`关于
GetOwner()的部分)
。猜测它当时找不到匹配的进程。因此您需要对此进行解释。失败的一行可能是这个`User=(gwmi Win32_进程-ComputerName$ComputerName….`关于
GetOwner()的部分)
。猜测它当时找不到匹配的进程。所以你需要解释一下。谢谢。你说得对。我忘了第41行是多行命令,所以没有检查第42-47行:/OK
$StillExists=gwmi Win32\u进程-ComputerName$ComputerName-Credential$Credential |在哪里{$\.ProcessId-eq$Process.IDProcess}尝试{$Owner=$StillExists.GetOwner().User}最后{
给出了无法对空值表达式调用方法的提示。+$User=$StillExists.GetOwner().User+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~类别信息:无效操作:(:)[],RuntimeException+FullyQualifiedErrorId:InvokeMethodUnull我以为
Try
会停止错误?
Try
只会停止终止错误。这就是为什么我在测试中使用truthy语句的原因。$stillexists在您的场景中为null。谢谢。您刚才说到点子上了。我忘了第41行是一个多行命令,所以没有t检查第42-47行:/OK
$StillExists=gwmi Win32_进程-ComputerName$ComputerName-Credential$Credential |其中{$\进程ID-eq$Process.IDProcess}最后尝试{$Owner=$StillExists.GetOwner().User}{
给出了无法对空值表达式调用方法的提示。+$User=$StillExists.GetOwner().User+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~,RuntimeException+FullyQualifiedErrorId:InvokeMethodUnull我以为
Try
会停止错误?
Try
只会停止终止错误。这就是为什么我在测试中使用truthy语句的原因。$stillexists在您的场景中为空。