TypeName.psm1

<#
.SYNOPSIS
Get a data-type information about a object.
.DESCRIPTION
Get a data-type information about a object.
If the variable is a COM object, this function returns a interface name.
.PARAMETER InputObject
Any object.
.PARAMETER ProgId
ProgID you wants to get a interface name.
.OUTPUTS
System.String
.EXAMPLE
Get-TypeName 1.0
 
System.Double
.EXAMPLE
Get-TypeName (New-Object -ComObject Scripting.Dictionary)
 
IDictionary
.EXAMPLE
Get-TypeName -ProgId WbemScripting.SWbemLocator
 
ISWbemLocator
#>

function Get-TypeName {
    [CmdletBinding(DefaultParameterSetName = 'InputObject')]
    [OutputType([string])]
    param (
        [Parameter(ParameterSetName = 'Pipeline', ValueFromPipeline)]
        [Parameter(ParameterSetName = 'InputObject', Mandatory, Position = 0)][AllowNull()]
        [Object]$InputObject,
        [Parameter(ParameterSetName = 'ProgId', Mandatory)][ValidateNotNullOrEmpty()]
        [string]$ProgId
    )

    process {
        if ($PSCmdlet.ParameterSetName -eq 'Pipeline') {
            return Get-TypeName $_
        }
    }

    end {
        if ($PSCmdlet.ParameterSetName -eq 'ProgId') {
            $comObject = New-Object -ComObject $ProgId
            if ($comObject) { return Get-TypeName $comObject } else { return }
        }

        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            if ($null -eq $InputObject) { return 'Null' }
            if ($InputObject -is [__ComObject]) {
                Write-Verbose 'Type: ComObject'
                if ($PSVersionTable['PSVersion'] -ge '6.0') {
                    $pstypename = $InputObject.pstypenames[0]
                    $interfaceKey = "Registry::HKEY_CLASSES_ROOT\Interface\$(($pstypename -split '#')[1])"
                    if (Test-Path $interfaceKey) {
                        return (Get-Item $interfaceKey).GetValue('')
                    } else {
                        return $pstypename
                    }
                } else {
                    Add-Type -AssemblyName Microsoft.VisualBasic
                    return [Microsoft.VisualBasic.Information]::TypeName($InputObject)
                }
            }
            if ($InputObject -is [ciminstance]) {
                Write-Verbose 'Type: CimInstance'
                return $InputObject.CimClass.ToString()
            }
            if ($InputObject -is [wmi]) {
                Write-Verbose 'Type: WmiObject'
                $classPath = $InputObject.ClassPath
                return "$($classPath.NamespacePath):$($classPath.ClassName)"
            }
            if ($InputObject.GetType().FullName -eq 'System.Management.Automation.PSCustomObject') {
                $pstypename = $InputObject.pstypenames[0]
                if ($pstypename -ne 'System.Management.Automation.PSCustomObject') {
                    Write-Verbose 'Type: PSCustomObject'
                    return $pstypename
                }
            }

            Write-Verbose 'Type: .NetObject'
            return $InputObject.GetType().ToString()
        }
    }
}

<#
.SYNOPSIS
Get a String value containing the PowerShell data type name (type accelerator).
.PARAMETER Name
Type name used by the common language runtime.
.OUTPUTS
System.String
.EXAMPLE
Get-PsTypeName System.Int32
 
int
#>

function Get-PsTypeName {
    [CmdletBinding()]
    [OutputType([string])]
    param (
        [Parameter(Mandatory, ValueFromPipeline, Position = 0)][ValidateNotNullOrEmpty()]
        [string]$Name
    )

    $types = [psobject].Assembly.GetType('System.Management.Automation.TypeAccelerators')::Get.GetEnumerator()
    foreach ($pair in $types) {
        try {
            if ([type]$Name -eq $pair.Value) { return $pair.Key }
        } catch [System.Management.Automation.PSInvalidCastException] {
            continue
        }
    }

    return $null
}