TypeName.psm1

using namespace Microsoft.VisualBasic
using namespace System.Collections.Generic
using namespace System.Management.Automation

function Get-TypeName {
    <#
    .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
    PS >Get-TypeName 1.0
 
    System.Double
    .EXAMPLE
    PS >$fso = New-Object -ComObject Scripting.Dictionary
    PS >Get-TypeName $fso
 
    IDictionary
    .EXAMPLE
    PS >Get-TypeName -ProgId WScript.Shell
 
    IWshShell3
    #>


    [CmdletBinding(DefaultParameterSetName = 'InputObject')]
    [OutputType([string])]
    param (
        [Parameter(ParameterSetName = 'InputObject', ValueFromPipeline, Position = 0)]
        [Object]$InputObject,
        [Parameter(ParameterSetName = 'ProgId', Mandatory)][ValidateNotNullOrEmpty()]
        [string]$ProgId
    )

    begin {
        if ($PSCmdlet.ParameterSetName -eq 'ProgId') {
            try {
                $InputObject = New-Object -ComObject $ProgId
            } catch {
                $PSCmdlet.WriteError($_)
            }
        }
    }

    process {
        if ($null -eq $InputObject) {
            Write-Verbose 'Type: Null'
            return
        }
        if ($InputObject -is [__ComObject]) {
            Write-Verbose 'Type: ComObject'
            if ($PSVersionTable['PSVersion'] -ge '6.0') {
                $pstypename = $InputObject.pstypenames[0]
                $interfaceId = ($pstypename -split '#')[1]
                $interfaceKey = "Registry::HKEY_CLASSES_ROOT\Interface\$interfaceId"
                if ($interfaceId -and (Test-Path $interfaceKey)) {
                    return (Get-Item $interfaceKey).GetValue('')
                } else {
                    return $pstypename
                }
            } else {
                Add-Type -AssemblyName Microsoft.VisualBasic
                return [Information]::TypeName($InputObject)
            }
        }
        if ($InputObject -is [ciminstance]) {
            Write-Verbose 'Type: CimInstance'
            $properties = $InputObject.CimClass.psbase.CimSystemProperties
            return "$($InputObject.GetType().FullName)#$($properties.Namespace)/$($properties.ClassName)"
        }
        if ($InputObject -is [wmi]) {
            Write-Verbose 'Type: WmiObject'
            $classPath = $InputObject.ClassPath
            return "$($InputObject.GetType().FullName)#$($classPath.NamespacePath)\$($classPath.ClassName)"
        }

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

function Get-PsTypeName {
    <#
    .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.Boolean
 
    bool
    .EXAMPLE
    Get-PsTypeName System.Int32
 
    int, int32
    #>


    [CmdletBinding()]
    [OutputType([string])]
    param (
        [Parameter(Mandatory, ValueFromPipeline, Position = 0)][ValidateNotNullOrEmpty()]
        [string]$Name
    )

    begin {
        $ret = [List[string]]::new()
        $types = [psobject].Assembly.GetType('System.Management.Automation.TypeAccelerators')::Get.GetEnumerator() |
            Sort-Object Key
    }

    process {
        try {
            $type = [type]$Name
            $ret.Clear()
            foreach ($pair in $types) {
                if ($type -eq $pair.Value) { $ret.Add($pair.Key) }
            }
            if ($ret.Length) { Write-Output ($ret -join ', ') }
        } catch {
            $PSCmdlet.WriteError($_)
        }

    }
}