MemoryTools.psm1
#region Define functions Function Get-MemoryUsage { [cmdletbinding(DefaultParameterSetName = 'ComputernameSet')] Param( [Parameter( Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'ComputernameSet' )] [ValidateNotNullorEmpty()] [Alias("cn")] [string[]]$Computername = $env:Computername, [ValidateSet("All", "OK", "Warning", "Critical")] [string]$Status = "All", [Parameter(ParameterSetName = 'CimInstanceSessionSet', Mandatory, ValueFromPipeline)] [ValidateNotNullorEmpty()] [Microsoft.Management.Infrastructure.CimSession[]]$CimSession ) Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" Write-Verbose "[BEGIN ] PSBoundParameters" Write-Verbose ($PSBoundParameters | Out-String) $MyCimSession = @() } #begin Process { Write-Verbose "[PROCESS] Using parameter set $($PSCmdlet.ParameterSetName)" if ($pscmdlet.ParameterSetName -eq 'ComputerNameSet') { #create a temporary cimsession if using a computername foreach ($item in $Computername) { Try { Write-Verbose "[PROCESS] Creating temporary CIM Session to $item" $MyCIMSession += New-CimSession -ComputerName $item -ErrorAction Stop -OutVariable +tmpSess Write-Verbose "[PROCESS] Added session" } Catch { Write-Error "[$($item.toUpper())] Failed to create temporary CIM Session. $($_.exception.message)" } } #foreach item in computername } #if computername parameter set else { Write-Verbose "[PROCESS] Re-using CimSessions" $MyCimSession = $CimSession } foreach ($session in $MyCIMSession) { Write-Verbose "[PROCESS] Processing $($session.computername)" Try { $os = Get-CimInstance -classname Win32_OperatingSystem -CimSession $session -ErrorAction stop } Catch { Write-Error "[$($session.Computername.toUpper())] Failed to retrieve data. $($_.exception.message)" } if ($os) { # Determine if Dynamic Memory is used $MaxDynamicMemory = (Get-Counter -Counter "\Hyper-V Dynamic Memory Integration Service\Maximum Memory, Mbytes" -ComputerName $os.PSComputerName -ErrorAction SilentlyContinue).CounterSamples.CookedValue * 1KB # Determine the amount of free memory if ($MaxDynamicMemory) { $FreeMemory = $os.FreePhysicalMemory + ($MaxDynamicMemory - $os.TotalVisibleMemorySize) $TotalMemory = $MaxDynamicMemory } else { $FreeMemory = $os.FreePhysicalMemory $TotalMemory = $os.TotalVisibleMemorySize } $pctFree = [math]::Round(($FreeMemory / $TotalMemory) * 100, 2) if ($pctFree -ge $MemoryToolsOK) { $StatusProperty = "OK" } elseif ($pctFree -ge $MemoryToolsWarning ) { $StatusProperty = "Warning" } else { #anything else is considered critical $StatusProperty = "Critical" } $obj = $os | Select @{Name = "Computername"; Expression = { $_.PSComputername.toUpper()}}, @{Name = "Status"; Expression = {$StatusProperty}}, @{Name = "PctFree"; Expression = {$pctFree}}, @{Name = "FreeGB"; Expression = {[math]::Round($FreeMemory / 1mb, 2)}}, @{Name = "TotalGB"; Expression = {[int]($TotalMemory / 1mb)}} #add a custom type name $obj.psobject.typenames.insert(0, "MyMemoryUsage") #write object to the pipeline if ($Status -eq 'All') { $obj } else { #write filtered results $obj | Where {$_.Status -match $Status} } #reset variables just in case Clear-Variable OS, obj, Mycimsession } #if OS } #foreach #clean up if ($tmpSess) { Write-Verbose "[PROCESS] Removing temporary sessions" $tmpSess | Remove-CimSession remove-Variable tmpsess } } #process End { Write-Verbose "[END ] $($MyInvocation.Mycommand)" } #end } #end Get-MemoryUsage Function Show-MemoryUsage { [cmdletbinding(DefaultParameterSetName = 'ComputernameSet')] Param( [Parameter( Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'ComputernameSet' )] [ValidateNotNullorEmpty()] [Alias("cn")] [string[]]$Computername = $env:Computername, [Parameter(ParameterSetName = 'CimInstanceSessionSet', Mandatory, ValueFromPipeline)] [ValidateNotNullorEmpty()] [Microsoft.Management.Infrastructure.CimSession[]]$CimSession ) Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" Write-Verbose "[BEGIN ] PSBoundParameters" Write-Verbose ($PSBoundParameters | Out-String) #a formatted report title $title = @" **************** * Memory Check * **************** "@ Write-Host $title -foregroundColor Cyan #initialize an array to hold data $data = @() } #begin Process { Write-Verbose "[PROCESS] Using parameter set $($PSCmdlet.ParameterSetName)" if ($pscmdlet.ParameterSetName -eq 'ComputerNameSet') { foreach ($Computer in $Computername) { #get memory usage data for each computer $data += Get-MemoryUsage -Computername $computer } } else { foreach ($session in $CIMSession) { #get memory usage data for each computer $data += Get-MemoryUsage -CimSession $session } } } #Process End { #write results to the host #create a text table and split into an array based on each line $strings = ($data | Format-Table | Out-String).Trim().split("`n") #display the first two lines which should be the header $strings | select -first 2 | write-host -ForegroundColor Cyan #process remaining lines $strings | select -Skip 2 | foreach { #check for the status and select an appropriate color Switch -regex ($_) { "OK" { $color = "Green" } "Warning" { $color = "Yellow" } "Critical" {$color = "Red" } } #write the line with the corresponding alert color Write-Host $_ -ForegroundColor $color } #foreach string #write an extra blank line write-Host "`n" Write-Verbose "[END ] $($MyInvocation.Mycommand)" } #end } #end Show-MemoryUsage Function Test-MemoryUsage { #get-memory usage and test for a minimum %free, FreeGB, TotalGB or UsedGB [cmdletbinding(DefaultParameterSetName = 'PercentComputer')] Param( [ValidateNotNullorEmpty()] [Alias("cn")] [Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "PercentComputer")] [Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "FreeComputer")] [Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "TotalComputer")] [Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "UsedComputer")] [string[]]$Computername = $env:Computername, [Parameter(Mandatory, ParameterSetName = "PercentCIM")] [Parameter(Mandatory, ParameterSetName = "FreeCIM")] [Parameter(Mandatory, ParameterSetName = "TotalCIM")] [Parameter(Mandatory, ParameterSetName = "UsedCIM")] [Microsoft.Management.Infrastructure.CimSession[]]$CimSession, [Parameter(HelpMessage = "Enter the minimum % free memory", ParameterSetName = "PercentComputer")] [Parameter(HelpMessage = "Enter the minimum % free memory", ParameterSetName = "PercentCIM")] [ValidateNotNullorEmpty()] [int]$PercentFree = 50, [Parameter(HelpMessage = "Enter the minimum free memory in GB", Mandatory, ParameterSetName = "FreeComputer")] [Parameter(HelpMessage = "Enter the minimum free memory in GB", Mandatory, ParameterSetName = "FreeCIM")] [ValidateNotNullorEmpty()] [double]$FreeGB, [ValidateNotNullorEmpty()] [Parameter(HelpMessage = "Enter the minimum total memory in GB", Mandatory, ParameterSetName = "TotalComputer")] [Parameter(HelpMessage = "Enter the minimum total memory in GB", Mandatory, ParameterSetName = "TotalCIM")] [int]$TotalGB, [Parameter(HelpMessage = "Enter the minimum amount of used memory in GB", Mandatory, ParameterSetName = "UsedComputer")] [Parameter(HelpMessage = "Enter the minimum amount of used memory in GB", Mandatory, ParameterSetName = "UsedCIM")] [ValidateNotNullorEmpty()] [double]$UsedGB, [switch]$Quiet ) Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" Write-Verbose "[BEGIN ] PSBoundParameters" Write-Verbose ($PSBoundParameters | Out-String) } #begin Process { if ($Computername) { $usage = foreach ($Computer in $Computername) { #get memory usage data for each computer Get-MemoryUsage -Computername $computer } } else { $usage = foreach ($session in $CIMSession) { #get memory usage data for each computer Get-MemoryUsage -CimSession $session -ErrorAction } } Foreach ($mem in $usage) { Switch -regex ($PSCmdlet.ParameterSetName) { "Used" { Write-Verbose "[PROCESS] Testing if Used GB is >= to $UsedGB" $used = $mem.TotalGB - $mem.FreeGB Write-Verbose "[PROCESS] Used = $used" if ($Used -ge $usedGB) { $Test = $True } else { $Test = $False } $data = $mem | Select Computername, @{Name = "UsedGB"; Expression = {$used}}, @{Name = "Test"; Expression = {$test}} } "Total" { Write-Verbose "[PROCESS] Testing if Total size is >= $TotalGB" if ($mem.TotalGB -ge $TotalGB) { $Test = $True } else { $Test = $False } $data = $mem | Select Computername, TotalGB, @{Name = "Test"; Expression = {$test}} } "Free" { Write-Verbose "[PROCESS] Testing if Free GB is >= $FreeGB" if ($FreeGB -le $mem.FreeGB) { $Test = $True } else { $Test = $False } $data = $mem | Select Computername, FreeGB, @{Name = "Test"; Expression = {$test}} } "Percent" { Write-Verbose "[PROCESS] Testing if Percent free is >= $PercentFree" if ($mem.PctFree -ge $percentFree) { $Test = $True } else { $Test = $False } $data = $mem | Select Computername, PctFree, @{Name = "Test"; Expression = {$test}} } } #switch if ($Quiet) { $Test } else { $data } } #foreach $mem } #process End { Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } #end } #end Test-MemoryUsage Function Get-MemoryPerformance { [cmdletbinding()] Param( [Parameter( Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'ComputernameSet' )] [ValidateNotNullorEmpty()] [Alias("cn")] [string[]]$Computername = $env:Computername, [Parameter( ParameterSetName = 'CimInstanceSessionSet', Mandatory, ValueFromPipeline )] [ValidateNotNullorEmpty()] [Microsoft.Management.Infrastructure.CimSession[]]$CimSession ) Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" <# Get all memory performance counters. Assuming counters on the client are the same as on the server. Sort by name. #> $all = (Get-Counter -ListSet Memory*).counter | Sort-Object #get a list of class properties. Some of the properties don't #appear to have any values and are different than what you get #with Get-Counter $perfclass = Get-CimClass -classname Win32_PerfFormattedData_PerfOS_Memory $selected = $perfclass.CimClassProperties | select -Skip 9 -expandProperty Name $selected += @{Name = "DateTime"; Expression = {(Get-Date)}} $selected += @{Name = "ComputerName"; Expression = {$session.ComputerName }} Write-Verbose "[BEGIN ] PSBoundParameters" Write-Verbose ($PSBoundParameters | Out-String) } #begin Process { Write-Verbose "[PROCESS] Using parameter set $($PSCmdlet.ParameterSetName)" if ($pscmdlet.ParameterSetName -eq 'ComputerNameSet') { #create a temporary cimsession if using a computername $MyCIMSession = foreach ($item in $Computername) { Try { Write-Verbose "[PROCESS] Creating temporary CIM Session to $item" New-CimSession -ComputerName $item -ErrorAction Stop -OutVariable +tmpSess Write-Verbose "[PROCESS] Added session" } Catch { Write-Error "[$($item.toUpper())] Failed to create temporary CIM Session. $($_.exception.message)" } } #foreach item in computername } #if computername parameter set else { Write-Verbose "[PROCESS] Re-using CimSessions" $MyCimSession = $CimSession } foreach ($session in $MyCIMSession) { Try { Get-CimInstance -classname Win32_PerfFormattedData_PerfOS_Memory -CimSession $session | Select-Object -property $selected } #try Catch { Write-Error "Failed to get performance data from $($session.computername.toupper()). $($_.exception.message)" } } #foreach #clean up if ($tmpSess) { Write-Verbose "[PROCESS] Removing temporary sessions" $tmpSess | Remove-CimSession Remove-Variable tmpsess } } #process End { Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } #end } #end Get-MemoryPerformance Function Get-PhysicalMemory { [cmdletbinding(DefaultParameterSetName = "ComputerNameSet")] Param( [Parameter( Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'ComputernameSet' )] [ValidateNotNullorEmpty()] [Alias("cn")] [string[]]$Computername = $env:Computername, [Parameter( ParameterSetName = 'CimInstanceSessionSet', Mandatory, ValueFromPipeline )] [ValidateNotNullorEmpty()] [Microsoft.Management.Infrastructure.CimSession[]]$CimSession ) Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" Write-Verbose "[BEGIN ] PSBoundParameters" Write-Verbose ($PSBoundParameters | Out-String) #define a hash table to resolve Form factor $form = @{ 0 = 'Unknown' 1 = 'Other' 2 = 'SIP' 3 = 'DIP' 4 = 'ZIP' 5 = 'SOJ' 6 = 'Proprietary' 7 = 'SIMM' 8 = 'DIMM' 9 = 'TSOP' 10 = 'PGA' 11 = 'RIMM' 12 = 'SODIMM' 13 = 'SRIMM' 14 = 'SMD' 15 = 'SSMP' 16 = 'QFP' 17 = 'TQFP' 18 = 'SOIC' 19 = 'LCC' 20 = 'PLCC' 21 = 'BGA' 22 = 'FPBGA' 23 = 'LGA' } } #begin Process { Write-Verbose "[PROCESS] Using parameter set $($PSCmdlet.ParameterSetName)" if ($pscmdlet.ParameterSetName -eq 'ComputerNameSet') { #create a temporary cimsession if using a computername $MyCIMSession = foreach ($item in $Computername) { Try { Write-Verbose "[PROCESS] Creating temporary CIM Session to $item" New-CimSession -ComputerName $item -ErrorAction Stop -OutVariable +tmpSess Write-Verbose "[PROCESS] Added session" } Catch { Write-Error "[$($item.toUpper())] Failed to create temporary CIM Session. $($_.exception.message)" } } #foreach item in computername } #if computername parameter set else { Write-Verbose "[PROCESS] Re-using CimSessions" $MyCimSession = $CimSession } foreach ($session in $MyCIMSession) { Write-Verbose "[PROCESS] Processing $($session.computername)" Try { Get-CimInstance -classname win32_physicalmemory -cimsession $session | Select @{Name = "Computername"; Expression = {$_.PSComputername.ToUpper()}}, Manufacturer, @{Name = "CapacityGB"; Expression = {$_.Capacity / 1GB}}, @{Name = "Form"; Expression = {$form.item($_.FormFactor -as [int])}}, @{Name = "ClockSpeed"; Expression = {$_.ConfiguredClockSpeed}}, @{Name = "Voltage"; Expression = {$_.ConfiguredVoltage}}, DeviceLocator } #Try Catch { Write-Error "[$($Session.ComputerName.toUpper())] $($_.exception.message)" } } #foreach #clean up if ($tmpSess) { Write-Verbose "[PROCESS] Removing temporary sessions" $tmpSess | Remove-CimSession Remove-Variable tmpsess } } #process End { Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } #end } #get-PhysicalMemory Function Get-TopProcessMemory { [cmdletbinding(DefaultParameterSetName = "ComputerNameSet")] Param( [Parameter( Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'ComputernameSet' )] [ValidateNotNullorEmpty()] [Alias("cn")] [string[]]$Computername = $env:Computername, [Parameter( ParameterSetName = 'CimInstanceSessionSet', Mandatory, ValueFromPipeline )] [ValidateNotNullorEmpty()] [Microsoft.Management.Infrastructure.CimSession[]]$CimSession, [validateRange(1, 25)] [int]$Top = 5 ) Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" Write-Verbose "[BEGIN ] PSBoundParameters" Write-Verbose ($PSBoundParameters | Out-String) } Process { Write-Verbose "[PROCESS] Using parameter set $($PSCmdlet.ParameterSetName)" if ($pscmdlet.ParameterSetName -eq 'ComputerNameSet') { #create a temporary cimsession if using a computername $MyCIMSession = foreach ($item in $Computername) { Try { Write-Verbose "[PROCESS] Creating temporary CIM Session to $item" New-CimSession -ComputerName $item -ErrorAction Stop -OutVariable +tmpSess Write-Verbose "[PROCESS] Added session" } Catch { Write-Error "[$($item.toUpper())] Failed to create temporary CIM Session. $($_.exception.message)" } } #foreach item in computername } #if computername parameter set else { Write-Verbose "[PROCESS] Re-using CimSessions" $MyCimSession = $CimSession } foreach ($session in $MyCIMSession) { Try { Write-Verbose "[PROCESS] Querying $($session.computername.ToUpper())" Get-CimInstance -classname win32_process -CimSession $session -PipelineVariable pv | sort WorkingSetSize -Descending | Select -first $Top -Property @{Name = "Computername"; Expression = {$_.PSComputername}}, ProcessID, Name, @{Name = "WS(MB)"; Expression = {$_.WorkingSetSize / 1MB}}, @{Name = "PctUsed"; Expression = { $os = Get-ciminstance win32_operatingsystem -ComputerName $pv.pscomputername $used = $os.TotalVisibleMemorySize - $os.FreePhysicalMemory [math]::Round(($_.workingsetsize / ($used * 1KB)) * 100, 2)} }, CreationDate, @{Name = "RunTime"; Expression = {(Get-Date) - $_.CreationDate}}, Commandline, @{Name = "Owner"; Expression = { $own = $pv | Invoke-CimMethod -MethodName GetOwner "$($own.domain)\$($own.user)" } } } #Try Catch { Write-Error "[$($Session.Computername.toUpper())] $($_.exception.message)" } #Catch } #foreach #clean up if ($tmpSess) { Write-Verbose "[PROCESS] Removing temporary sessions" $tmpSess | Remove-CimSession Remove-Variable tmpsess } } #process End { Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } #end } #end function #endregion #import module variables and aliases . $PSScriptRoot\MemoryToolsSettings.ps1 |