# encoding: ascii
# api: csharp
# title: Get-CharInfo
# description: Gets Unicode information about a character. If you have charmap.exe installed it will use its getuname.dll to get a descriptive string about the character.
# version: 0.1
# type: class
# author: Public Domain
# license: CC0
# function: Get-CharInfo
# x-poshcode-id: 5230
# x-archived: 2016-10-26T08:37:46
# x-published: 2016-06-09T05:12:00
#
#
<#
Use this like this:
"abc",([char]'x'),0xBF | Get-CharInfo
#>
Set-StrictMode -Version latest
if (Test-Path -LiteralPath "$([System.Environment]::SystemDirectory -replace '\\','\\')\\getuname.dll") {
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
namespace Microsofts.CharMap {
public class UName {
[DllImport("$([System.Environment]::SystemDirectory -replace '\\','\\')\\getuname.dll", ExactSpelling=true, SetLastError=true)]
private static extern int GetUName(ushort wCharCode, [MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder buf);
public static string Get(char ch) {
var sb = new System.Text.StringBuilder(300);
UName.GetUName(ch, sb);
return sb.ToString();
}
}
}
"@
} else {
Add-Type -TypeDefinition @"
using System;
namespace Microsofts.CharMap {
public class UName {
public static string Get(char ch) { return "???"; }
}
}
"@
}
function Get-CharInfo {
[CmdletBinding()]
param(
[Parameter(Position = 0, Mandatory, ValueFromPipeline)]
$InputObject
)
begin {
function out {
param($ch)
if (0 -gt $ch) { return }
if (0xFFFF -ge $ch) {
[pscustomobject]@{
Char = [char]$ch
CodePoint = 'U+{0:X4}' -f $ch
Category = [System.Globalization.CharUnicodeInfo]::GetUnicodeCategory($ch)
Description = [Microsofts.CharMap.UName]::Get($ch)
}
} elseif (0x10FFFF -ge $ch) {
$s = [char]::ConvertFromUtf32($ch)
[pscustomobject]@{
Char = $s
CodePoint = 'U+{0:X}' -f $ch
Category = [System.Globalization.CharUnicodeInfo]::GetUnicodeCategory($s, 0)
Description = '???'
}
}
}
}
process {
if ($InputObject -as [char]) {
out ([int][char]$InputObject)
} elseif ($InputObject -isnot [string] -and $InputObject -as [int]) {
out ([int]$InputObject)
} else {
$InputObject = [string]$InputObject
for ($i = 0; $i -lt $InputObject.Length; ++$i) {
if ([char]::IsHighSurrogate($InputObject[$i]) -and (1+$i) -lt $InputObject.Length -and [char]::IsLowSurrogate($InputObject[$i+1])) {
out ([char]::ConvertToUtf32($InputObject, $i))
++$i
} else {
out ([int][char]$InputObject[$i])
}
}
}
}
}