CPU and Physical Memory Status

Good Morning Everyone,
This is my first post here, and I’m just getting started with PowerShell. I have been watching some MVA videos and doing research online, but I still need some help with this code. Basically, our network has over 50 virtual servers that we need to monitor daily, and my particular task is to write a script to create an output file showing CPU and Physical Memory usage as a percent for each of those servers.

A friend of mine helped me throw this together, and I understand the basics of it, but it’s not quite giving me everything I want to see. I found out that “Commited_MBytes” is not the same thing as “Physical Memory”. What I need is basically the same output that you would see if you opened task manager. The CPU portion is fine.

$servers = Get-Content .\server_list.txt
$fileName = "..\..\scriptOutputFiles\get_CPU_MEM_output_$(get-date -f yyyy-MM-dd).txt"

foreach($server in $servers)
{
    if (!(Test-Connection $server -quiet))
    {
        Write-Output "******************* Problem connecting to $server *****************************" | Out-File -FilePath $fileName -Width 75 -Append
    }
    else
    {
        Write-Output "Server details for: $server" | Out-File -FilePath $fileName -Width 75 -Append

        Write-Output "PROCINFO" | Out-File -FilePath $fileName -Width 75 -Append
        Get-WmiObject -ComputerName $server -Class Win32_PerfFormattedData_PerfOS_Processor | Format-Table @{Name="Proc#"; Expression = {($_.Name)}},
                        @{Name="Percent_Used"; Expression = {($_.PercentProcessorTime)}},
                        @{Name="Percent_Idle"; Expression = {($_.PercentIdleTime)}} | Out-File -FilePath $fileName -width 75 -append

        Write-Output "MEMINFO" | Out-File -FilePath $fileName -Width 75 -Append
        Get-WmiObject -ComputerName $server -Class Win32_PerfFormattedData_PerfOS_Memory | Format-Table @{Name="Percent_Commited_Bytes"; Expression = {($_.PercentCommittedBytesInUse)}},
                        @{Name="Available_MBytes"; Expression = {($_.AvailableMBytes)}},
                        @{Name="Committed_MBytes"; Expression = {[Math]::Round($_.CommittedBytes/1024/1024, 1)}} | Out-File -FilePath $fileName -width 75 -append
    }
}

There is no company specific information in this script, and server_list.txt is literally just a list of servers for the script to reference:

Server A
Server B
Server C
Etc…

Any help would be greatly appreciated.

So, the first thing I think is important to understand is that you can do so much more collecting data as an object. Once you have a PSObject you can do analytics, reporting and use the data across Powershell’s pipeline. Try to collect your data like this:

$fileName = "..\..\scriptOutputFiles\get_CPU_MEM_output_$(get-date -f yyyy-MM-dd).txt"

$results = foreach($server in $servers)
{
    if (!(Test-Connection $server -quiet))
    {
        New-Object -TypeName PSObject -Property @{
            "ComputerName"           = $server
            "Proc#"                  = $null
            "Percent_Used"           = $null
            "Percent_Idle"           = $null
            "Percent_Commited_Bytes" = $null
            "Available_MBytes"       = $null
            "Committed_MBytes"       = $null
            "Status"                 = "Failed: Unable to ping."
        }
    }
    else
    {
        $perfProc = Get-WmiObject -ComputerName $server -Class Win32_PerfFormattedData_PerfOS_Processor | 
        Select -Property @{Name="Proc#"; Expression = {($_.Name)}},
                         @{Name="Percent_Used"; Expression = {($_.PercentProcessorTime)}},
                         @{Name="Percent_Idle"; Expression = {($_.PercentIdleTime)}}

        $perfOS = Get-WmiObject -ComputerName $server -Class Win32_PerfFormattedData_PerfOS_Memory | 
        Select -Property @{Name="Percent_Commited_Bytes"; Expression = {($_.PercentCommittedBytesInUse)}},
                         @{Name="Available_MBytes"; Expression = {($_.AvailableMBytes)}},
                         @{Name="Committed_MBytes"; Expression = {[Math]::Round($_.CommittedBytes/1mb, 1)}}
        
        
        New-Object -TypeName PSObject -Property @{
            "ComputerName"           = $server
            "Proc#"                  = $perfProc."Proc#"
            "Percent_Used"           = $perfProc."Percent_Used"
            "Percent_Idle"           = $perfProc."Percent_Idle"
            "Percent_Commited_Bytes" = $perfOS."Percent_Commited_Bytes"
            "Available_MBytes"       = $perfOS."Available_MBytes"
            "Committed_MBytes"       = $perfOS."Committed_MBytes"
            "Status"                 = "Success"
        }
    }
}

$results

One of the other things Powershell has is a great community. Microsoft Script Center has tons of scripts for reports on almost anything you can imagine, so you could look at other examples of memory reports.

One last thing to keep in mind is that task manager is constantly monitoring memory and CPU, it’s a live stream. When you pull a report, it’s static so it’s possible it won’t match exactly.

Thank you Rob, the output on this might be easier to read for sure, but I just have a couple questions.

  1. I noticed that you deleted line 1 from my original code: “$servers = Get-Content .\server_list.txt”. I don’t see any other reference to my “server_list.txt” file in your code. Was this an accident, or am I missing something?

  2. In lines 20-28, it looks like you are calling up the same data I was, but I was wondering if there was a way to pull “Physical” memory vs “Committed” memory. I realize that task manager is live stream, but what I found out is that the “PercentCommittedBytesInUse” is not the same as what is showing in task manager for a particular server at the time I run my script. We have a few servers that have the occasional “runaway process” (usually dllhost.exe). We need to be able to catch a server using high amounts of memory without having to log into every server, every morning. This process eats up a lot of our time.

Thank you for your time, your code is quite elegant!

-Phil

bump

Last bump…thank you.