Skip to content

Instantly share code, notes, and snippets.

@Jaykul
Last active March 12, 2018 23:45
Show Gist options
  • Save Jaykul/8de83bb3ff299999be84 to your computer and use it in GitHub Desktop.
Save Jaykul/8de83bb3ff299999be84 to your computer and use it in GitHub Desktop.
LocalizeCounterNames
$Processor, $Privileged = Get-CounterLocalizedName "Processor", "% Privileged Time"
Get-Counter "\$Processor(_Total)\$Privileged"
Add-Type -Name PerfCounter -Namespace Win32 -MemberDefinition '
[DllImport("pdh.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern UInt32 PdhLookupPerfNameByIndex(
string szMachineName, uint dwNameIndex,
System.Text.StringBuilder szNameBuffer, ref uint pcchNameBufferSize);
[DllImport("pdh.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern UInt32 PdhExpandCounterPath(
string szWildCardPath,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)]
char[] mszExpandedPathList, ref uint pcchPathListLength);
[DllImport("pdh.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern UInt32 PdhLookupPerfIndexByName(
string szMachineName,
string szNameBuffer,
ref uint dwNameIndex
);
'
# Build a hash array of offsets into the counter buffer. Use the index
# values from the performance data queries to access the offsets.
function Get-CounterLocalizedName {
#.Synopsis
# Look up localized names for performance counters.
#.Description
# Users Remote Registry and PDH* functions to look up counters on remote computers
#.Example
# $Processor, $Privileged = Get-CounterLocalizedName "Processor", "% Privileged Time"
# Get-Counter "\$Processor(_Total)\$Privileged"
#
# Shows how to get counters in a culture-sensitive way.
param(
# The counter name to look up
[string[]]$Counter,
# The name of a computer to query against
[Alias("CN")]
$ComputerName = $env:COMPUTERNAME
)
if(!$global:LocalizedCounters) {
$global:LocalizedCounters = @{}
}
if(!$global:LocalizedCounters.ContainsKey($ComputerName)) {
$Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("PerformanceData", $ComputerName) # , "Registry32"
$Counters = $Reg.GetValue('Counter')
$Reg.Close()
#return registry values
$global:LocalizedCounters.$ComputerName = @{}
$global:LocalizedCounters.($ComputerName).ByIndex = @{}
$global:LocalizedCounters.($ComputerName).ByName = @{}
foreach($c in $Counters)
{
if($foreach.MoveNext()) {
$global:LocalizedCounters.($ComputerName).ByName.($foreach.Current) = $c
}
}
}
foreach($c in $Counter) {
$index = $global:LocalizedCounters.($ComputerName).ByName.($c)
if(!$global:LocalizedCounters.($ComputerName).ByIndex.ContainsKey($index)) {
$global:LocalizedCounters.($ComputerName).ByIndex.$Index = Invoke-PdhLookupPerfNameByIndex $Index $ComputerName
}
$global:LocalizedCounters.($ComputerName).ByIndex.$Index
}
}
set-alias Get-PerfName Invoke-PdhLookupPerfNameByIndex
set-alias gpn Invoke-PdhLookupPerfNameByIndex
function Invoke-PdhLookupPerfNameByIndex {
param(
[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[int]$Index,
[Alias("CN")]
$ComputerName = $env:COMPUTERNAME
)
process {
[UInt32]$BufferSize = 0
$Buffer = New-Object System.Text.StringBuilder $BufferSize
$ErrorCode = "{0:X}" -f [Win32.PerfCounter]::PdhLookupPerfNameByIndex($ComputerName, $Index, $Buffer, [Ref]$BufferSize)
if("800007D2" -eq $ErrorCode <# PDH_MORE_DATA #>) {
$Buffer = New-Object System.Text.StringBuilder $BufferSize
$ErrorCode = "{0:X}" -f [Win32.PerfCounter]::PdhLookupPerfNameByIndex($ComputerName, $Index, $Buffer, [Ref]$BufferSize)
}
if ($ErrorCode -eq "0")
{
$Buffer.ToString()
}
else
{
Write-Error ("ERRORCODE ${ErrorCode}: Unable to retrieve localized name!" +
"`nYou may look up the error code here https://msdn.microsoft.com/en-us/library/windows/desktop/aa373046"
)
}
}
}
set-alias Get-PerfIndex Invoke-PdhLookupPerfNameByIndex
set-alias gpi Invoke-PdhLookupPerfNameByIndex
function Invoke-PdhLookupPerfIndexByName {
param(
[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[string]$Name,
[Alias("CN")]
$ComputerName = $env:COMPUTERNAME
)
process {
[UInt32]$Index = 0
$ErrorCode = "{0:X}" -f [Win32.PerfCounter]::PdhLookupPerfIndexByName($ComputerName, $Name, [Ref]$Index)
if ($ErrorCode -eq "0")
{
$Index
} elseif($ErrorCode -eq "C0000BD4"){
Write-Error "ERRORCODE ${ErrorCode}: Unable to find the specified string ($Name) in the list of performance counter names and help-text strings"
} elseif($ErrorCode -eq "800007D0"){
Write-Error "ERRORCODE ${ErrorCode}: Unable to connect to the specified computer ($ComputerName), perhaps the computer is offline."
}
else
{
Write-Error ("ERRORCODE ${ErrorCode}: Unable to retrieve index!" +
"`nYou may look up the error code here https://msdn.microsoft.com/en-us/library/windows/desktop/aa373046"
)
}
}
}
function Invoke-PdhExpandCounterPath {
param($Path)
[UInt32]$BufferSize = 0
$Buffer = [char[]]""
$ErrorCode = "{0:X}" -f [Win32.PerfCounter]::PdhExpandCounterPath($Path, $Buffer, [Ref]$BufferSize)
if("800007D2" -eq $ErrorCode <# PDH_MORE_DATA #>) {
$Buffer = New-Object "char[]" $BufferSize
$ErrorCode = "{0:X}" -f [Win32.PerfCounter]::PdhExpandCounterPath($Path, $Buffer, [Ref]$BufferSize)
}
if("0" -eq $ErrorCode) {
(New-Object String $Buffer).Trim(([char]0)) -split ([char]0)
}
else
{
# TODO: possibly handle the error codes and print the real error message
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa373046%28v=vs.85%29.aspx
Write-Error (("ERRORCODE ${ErrorCode}: Unable to expand path." )+
" Please verify you passed a path like \\ComputerName\CounterPath*\Name" +
"`nYou may look up the error code here https://msdn.microsoft.com/en-us/library/windows/desktop/aa373046"
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment