This is another old WMI function I have rewritten to use CIM instead. This one queries computers for memory information.
function Get-PhysicalMemory { | |
<# | |
.SYNOPSIS | |
Get information about the physical memory installed on a computer. | |
.DESCRIPTION | |
This function uses CIM to query one or more computer for physical memory information. | |
It will first try to connect using 'WSMAN' protocol, but will fall back to using 'DCOM' if | |
this fails. | |
.EXAMPLE | |
Get-PhysicalMemory | |
Will query the local computer for physical memory information. | |
.EXAMPLE | |
Get-PhysicalMemory Server01 -Credential domain/user01 | |
Will try to query 'Server01' with the credentials of 'domain/user01'. | |
.OUTPUTS | |
PSObject | |
.NOTES | |
Author: Øyvind Kallstad | |
Date: 08.12.2014 | |
Version: 1.0 | |
#> | |
[CmdletBinding()] | |
param ( | |
# Specifies the target computer. Enter a fully qualified domain name, NetBIOS name, or an IP address. When the remote computer is in a different domain than the local computer, | |
# the fully qualified domain name is required. | |
[Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)] | |
[ValidateNotNullorEmpty()] | |
[string[]] $ComputerName = $env:COMPUTERNAME, | |
# Specifies a user account that has permission to perform this action. | |
[Parameter()] | |
[System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, | |
# Use this parameter to force the creation of a new CIM session. The default behaviour is to save the session and reuse it if possible. | |
[Parameter()] | |
[switch] $ForceNewCimSession | |
) | |
process { | |
foreach ($computer in $ComputerName) { | |
try { | |
# define hashtable for Test-WSMan properties | |
$wsmanProperties = @{ | |
ComputerName = $computer | |
ErrorAction = 'SilentlyContinue' | |
} | |
if ($PSBoundParameters['Credential']){ | |
$wsmanProperties.Authentication = 'Basic' | |
$wsmanProperties.Credential = $Credential | |
} | |
# check if wsman is responding | |
$wsmanTest = Test-WSMan @wsmanProperties | |
# based on whether the result of the wsman test, we decide on the protocol to use for the cim session | |
if (-not([string]::IsNullOrEmpty($wsmanTest))) { | |
$cimSessionOption = New-CimSessionOption –Protocol Wsman | |
Write-Verbose 'Using protocol "Wsman"' | |
} | |
else { | |
$cimSessionOption = New-CimSessionOption –Protocol Dcom | |
Write-Verbose 'Using protocol "Dcom"' | |
} | |
# define hashtable for cim session properties | |
$cimSessionProperties = @{ | |
Name = $computer | |
ComputerName = $computer | |
SessionOption = $cimSessionOption | |
Verbose = $false | |
ErrorAction = 'Stop' | |
} | |
if ($PSBoundParameters['Credential']){ $cimSessionProperties.Credential = $Credential} | |
# first check to see if a cim session already exist, if so use this – if not, we create a new one | |
# if -ForceNewCimSession is used, always create a new cim session | |
if ((-not($cimSession = Get-CimSession –Name $computer –ErrorAction SilentlyContinue)) -or ($ForceNewCimSession)) { | |
Write-Verbose 'Creating new CIM session' | |
$cimSession = New-CimSession @cimSessionProperties –SkipTestConnection | |
} else { Write-Verbose 'Using existing CIM session' } | |
# run query to get data | |
$physicalMemory = Get-CimInstance –CimSession $cimSession –Query 'SELECT BankLabel,Capacity,DataWidth,Description,DeviceLocator,FormFactor,InterleaveDataDepth,InterleavePosition,Manufacturer,MemoryType,PartNumber,PositionInRow,SerialNumber,Speed,Tag,TotalWidth,TypeDetail FROM Win32_PhysicalMemory' –Verbose:$false –ErrorAction Stop | |
foreach ($memory in $physicalMemory) { | |
switch($memory.FormFactor) { | |
'0' {$memoryFF = 'Unknown'} | |
'1' {$memoryFF = 'Other'} | |
'2' {$memoryFF = 'SIP'} | |
'3' {$memoryFF = 'DIP'} | |
'4' {$memoryFF = 'ZIP'} | |
'5' {$memoryFF = 'SOJ'} | |
'6' {$memoryFF = 'Proprietary'} | |
'7' {$memoryFF = 'SIMM'} | |
'8' {$memoryFF = 'DIMM'} | |
'9' {$memoryFF = 'TSOP'} | |
'10' {$memoryFF = 'PGA'} | |
'11' {$memoryFF = 'RIMM'} | |
'12' {$memoryFF = 'SODIMM'} | |
'13' {$memoryFF = 'SRIMM'} | |
'14' {$memoryFF = 'SMD'} | |
'15' {$memoryFF = 'SSMP'} | |
'16' {$memoryFF = 'QFP'} | |
'17' {$memoryFF = 'TQFP'} | |
'18' {$memoryFF = 'SOIC'} | |
'19' {$memoryFF = 'LCC'} | |
'20' {$memoryFF = 'PLCC'} | |
'21' {$memoryFF = 'BGA'} | |
'22' {$memoryFF = 'FPBGA'} | |
'23' {$memoryFF = 'LGA'} | |
DEFAULT {$memoryFF = 'Unknown'} | |
} | |
switch ($memory.MemoryType) { | |
'0' {$memoryType = 'Unknown'} | |
'1' {$memoryType = 'Other'} | |
'2' {$memoryType = 'DRAM'} | |
'3' {$memoryType = 'Synchronous DRAM'} | |
'4' {$memoryType = 'Cache DRAM'} | |
'5' {$memoryType = 'EDO'} | |
'6' {$memoryType = 'EDRAM'} | |
'7' {$memoryType = 'VRAM'} | |
'8' {$memoryType = 'SRAM'} | |
'9' {$memoryType = 'RAM'} | |
'10' {$memoryType = 'ROM'} | |
'11' {$memoryType = 'Flash'} | |
'12' {$memoryType = 'EEPROM'} | |
'13' {$memoryType = 'FEPROM'} | |
'14' {$memoryType = 'EPROM'} | |
'15' {$memoryType = 'CDRAM'} | |
'16' {$memoryType = '3DRAM'} | |
'17' {$memoryType = 'SDRAM'} | |
'18' {$memoryType = 'SGRAM'} | |
'19' {$memoryType = 'RDRAM'} | |
'20' {$memoryType = 'DDR'} | |
'21' {$memoryType = 'DDR-2'} | |
DEFAULT {$memoryType = 'Unknown'} | |
} | |
switch ($memory.InterleavePosition) { | |
'0' {$interleavePosition = 'NonInterleaved'} | |
'1' {$interleavePosition = 'First position' } | |
'2' {$interleavePosition = 'Second position'} | |
DEFAULT {$interleavePosition = 'unknown'} | |
} | |
$typeDetails = @() | |
if($memory.TypeDetail -band 1) {$typeDetails += 'Reserved'} | |
if($memory.TypeDetail -band 2) {$typeDetails += 'Other'} | |
if($memory.TypeDetail -band 4) {$typeDetails += 'Unknown'} | |
if($memory.TypeDetail -band 8) {$typeDetails += 'Fast-paged'} | |
if($memory.TypeDetail -band 16) {$typeDetails += 'Static column'} | |
if($memory.TypeDetail -band 32) {$typeDetails += 'Pseudo-static'} | |
if($memory.TypeDetail -band 64) {$typeDetails += 'RAMBUS'} | |
if($memory.TypeDetail -band 128) {$typeDetails += 'Synchronous'} | |
if($memory.TypeDetail -band 256) {$typeDetails += 'CMOS'} | |
if($memory.TypeDetail -band 512) {$typeDetails += 'EDO'} | |
if($memory.TypeDetail -band 1024){$typeDetails += 'Window DRAM'} | |
if($memory.TypeDetail -band 2048){$typeDetails += 'Cache DRAM'} | |
if($memory.TypeDetail -band 4096){$typeDetails += 'Nonvolatile'} | |
$output = [PSCustomObject] [Ordered] @{ | |
ComputerName = $computer | |
BankLabel = $memory.BankLabel | |
Capacity = $memory.Capacity | |
CapacityMB = ($memory.Capacity/1mb) | |
DataWidth = $memory.DataWidth | |
Description = $memory.Description | |
DeviceLocator = $memory.DeviceLocator | |
FormFactor = $memoryFF | |
InterleaveDataDepth = $memory.InterleaveDataDepth | |
InterleavePosition = $interleavePosition | |
Manufacturer = $memory.Manufacturer | |
MemoryType = $memoryType | |
PartNumber = $memory.PartNumber | |
PositionInRow = $memory.PositionInRow | |
SerialNumber = $memory.SerialNumber | |
Speed = $memory.Speed | |
Tag = $memory.Tag | |
TotalWidth = $memory.TotalWidth | |
TypeDetails = $typeDetails -join ', ' | |
} | |
$defaultProperties = @('ComputerName','BankLabel','DeviceLocator','CapacityMB','Speed','FormFactor','Manufacturer') | |
$defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$defaultProperties) | |
$PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet) | |
$output | Add-Member –MemberType MemberSet –Name PSStandardMembers –Value $PSStandardMembers –Force | |
Write-Output $output | |
Remove-Variable –Name memoryFF,interleavePosition,typeDetails,memoryType –ErrorAction SilentlyContinue | |
} | |
} | |
catch { | |
# if the connection fail we don't want to keep the session | |
Remove-CimSession –Name $computer –ErrorAction SilentlyContinue | |
Write-Warning "At line:$($_.InvocationInfo.ScriptLineNumber) char:$($_.InvocationInfo.OffsetInLine) Command:$($_.InvocationInfo.InvocationName), Exception: '$($_.Exception.Message.Trim())'" | |
} | |
} | |
} | |
} |
Nice! Really fast on my laptop! I like how it catches the errors gracefully. A bit against the best practices that huge “try{}catch{}” block, but why follow these guidlines if it is only to be a *$¨!# in the but!? (I actually know the answer: It is to have a more precise error handeling, and specifically, to be able to use the finally{} scriptblock).
I personally like to add a “Get-Credential” right after my credential variable when I use it. (But it will make it mandatory).
[System.Management.Automation.Credential()] $Credential = (Get-credential)
Great work!
LikeLike
Thanks. Yeah, I tend to use large try-catch blocks. For me it’s enough that I catch any exceptions. If I’m working on a really complicated script, I’ll do it differently of course, but these functions are really just meant to do small things, so it works well I think.
LikeLike