Reputation: 3
So, I am going to throw this out. I am trying to write a simple health check for a bunch of systems. I know there are products that do it and whatnot. This is a special isolated circumstance where unless the software has prior approval I cant even consider freeware options. I have cobbled together the following:
Clear-Host
$date = Get-Date -Format "yyyy-MM-dd"
$cpuTime = (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue
$availMem = (Get-Counter '\Memory\Available MBytes').CounterSamples.CookedValue / 1024
$totalRam = (Get-WmiObject Win32_ComputerSystem).totalphysicalmemory / (1024 * 1024 * 1024)
$DiskUsageC = (Get-Counter '\LogicalDisk(C:)\% Free Space').CounterSamples.CookedValue
$env:computername + "`t`t" + $date + "`t`t CPU Usage: " + $cpuTime.ToString("#,0.0") + "%" + "`t`t Memory Usage: " + ($availMem / $totalRam *100).ToString("#,0.0") + '%' + "`t`t Hard Disk Usage: " + " (C:) " + $DiskUsageC.ToString("#,0.0") + "%" | Out-GridView -Title 'System Health Check'
It is by no means perfect, or clean. I am an SA. Not a developer. Its cobbled together via tweaking other ppls code. My question is, is there a good way for rather than explicitly stating the drives in the code, I can set a variable and it adapts to the amount of drives and gives me their usage percentage? These are servers with different numbers of drives. Can anyone offer suggestions or point me in the right direction?
Thanks for any help in advance!
Upvotes: 0
Views: 99
Reputation: 25001
You can stick with your current format and just iterate through the logical drives/volumes:
$date = Get-Date -Format "yyyy-MM-dd"
$cpuTime = (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue
$availMem = (Get-Counter '\Memory\Available MBytes').CounterSamples.CookedValue / 1024
$totalRam = (Get-CimInstance Win32_ComputerSystem).totalphysicalmemory / (1024 * 1024 * 1024)
# List volumes if they have drive letters and are fixed (you can change this filter)
$drives = Get-Volume | Where {$_.DriveLetter -and $_.DriveType -eq 'Fixed'}
# Loop through each volume to create your formatted string
# $driveData is an array of those formatted strings.
$driveData = $drives | Foreach-Object {
$letter = $_.DriveLetter
"({0}:) {1}%" -f $letter,(Get-Counter "\LogicalDisk($($letter):)\% Free Space").CounterSamples.CookedValue.ToString('#,0.0')
}
$env:computername + "`t`t" + $date + "`t`t CPU Usage: " + $cpuTime.ToString("#,0.0") + "%" + "`t`t Memory Usage: " + ($availMem / $totalRam *100).ToString("#,0.0") + '%' + "`t`t Hard Disk Usage: $($driveData -join ', ')" |
Out-GridView -Title 'System Health Check'
Explanation:
There are some notable techniques used here to achieve the desired results. $()
is the sub-expression operator, which allows an expression to be evaluated within a string (code inside of double quotes). For example, "$($letter):"
allows $letter
to be substituted with its value and then have a :
appended to that value.
$($driveData -join ', ')
also occurs within double quotes (inside of an expandable string). This allows the elements of the array, $driveData
, to be joined into a single string. Then each of those elements are separated by ,
(comma and space).
Upvotes: 0
Reputation: 6860
So lets talk POWERSHELL.
In Powershell we love to Pipe |
. This means joining commands together to get the data we want. Once a command is done it will Pipe |
the response to the next command. There is a Magic variable used that represents that passed response which is $_
.
In this case looks like you want to build a type of sensor.
So lets solve the issue
There is a command called Get-PSDrive
it basically allows you to interact with with OS environment.
If you run Get-PSDrive
you will get stuff like
Name Used (GB) Free (GB) Provider Root CurrentLocation
---- --------- --------- -------- ---- ---------------
Alias Alias
C 101.05 314.08 FileSystem C:\ Users\Andrew Davis\Documents\Scripts\Powershell\Autoload\ActiveDirectory
Cert Certificate \
D 79.95 576.85 FileSystem D:\
What we are looking for is the Provider and the Provider we want is FileSystem.
So lets pipe
Get-PSDrive -PSProvider 'FileSystem' | Foreach-Object{
"Drive: $($_.Name), Free Space : $([math]::Round($_.Free / 1GB, 1)) GB"
}
Will return something like
Drive: C, Free Space : 314.1 GB
Drive: D, Free Space : 576.8 GB
Drive: E, Free Space : 0.8 GB
Drive: F, Free Space : 6.2 GB
Drive: G, Free Space : 73.3 GB
Drive: H, Free Space : 29 GB
Drive: I, Free Space : 6.6 GB
Drive: J, Free Space : 24 GB
Upvotes: 1