TypeAccelerators.psm1
Function Get-TypeAccelerator { <# .SYNOPSIS Gets Type Accelerators in the PowerShell Session .DESCRIPTION Get-TypeAccelerator gets the type accelerators of the current PowerShell session. It can also get indvidual accelerators using either the name of the accelerator or the type it references. There is a behavior to make note of when passing the type to the Type parameter: A type object can be piped in as a literal (surrounded by []), but cannot be supplied to the Type parameter as a literal. Instead, a string must be passed or cast to a type object before passing (using parentheses). This behavior does not affect input when the type is previously stored in a variable. See the examples for additional clarification. .PARAMETER Type The type to get from the type accelerators. .PARAMETER Name The name of the type accelerator to get. .INPUTS System.RuntimeType You can pipe System.RuntimeType objects to Add-TypeAccelerator System.String You can pipe type names as System.String to be converted to System.Type .OUTPUTS System.Collections.Generic.KeyValuePair[[System.String],[System.Type]] .EXAMPLE Get-TypeAccelerator This command will output all type accelerators in the PowerShell session. .EXAMPLE [System.Collections.ArrayList] | Get-TypeAccelerator This command will get any type accelerator that references the ArrayList type. Note the use of square brackests. .EXAMPLE Get-TypeAccelerator -Type System.Collections.ArrayList This command will get any type accelerator that references the ArrayList type. Note the lack of square brackests. .EXAMPLE Get-TypeAccelerator -Name AList This command will get any type acclerator with the name AList. .NOTES This script is based on the funciton found at http://poshcode.org/1869, but had to be updated to accomodate a change made in PowerShell 3.0/4.0. Author: Chris Carter Version: 1.2 .LINK http://poshcode.org/1869 #> #Requires -Version 2.0 [CmdletBinding(DefaultParameterSetName="Name")] Param( [Parameter(Position=0,ValueFromPipeline=$true,ParameterSetName="Name")] [String[]]$Name, [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="Type")] [Type[]]$Type ) Process { $Collection = $Name, $Type | Where-Object {$_} if ($Collection) { foreach ($object in $Collection) { $aClone = New-Object TADict -ArgumentList $accel::Get try { #Test to exclude accelerator names from being cast to type if (!$accel::Get.ContainsKey($object)) { $object = [Type]$object } } catch {} if ($object -is [Type]) { $output = $aClone.GetEnumerator() | Where-Object {$_.Value -eq $object} } elseif ($object -is [String]) { $output = $aClone.GetEnumerator() | Where-Object {$_.Key -eq $object} } foreach ($o in $output) { $o.PSObject.TypeNames.Insert(0, 'TypeAccelerator.KeyValuePair') $o } } } else { $kvPairs = (New-Object TADict -ArgumentList $accel::Get).GetEnumerator() foreach ($pair in $kvPairs) { $pair.PSObject.TypeNames.Insert(0, 'TypeAccelerator.KeyValuePair') $pair } } } } Function Add-TypeAccelerator { <# .SYNOPSIS Adds type accelerators to the PowerShell session .DESCRIPTION Add-TypeAccelerator adds type accelerators to the the PowerShell session to allow shortening of longer type names, such as [switch] for [System.Management.Automation.SwitchParameter]. The Type parameter will accept Type objects, strings of the type's full name, and hashtables with the desired accelerator name as the key and the type (as a string of the full name or the type object itself) as the value. The Name parameter, by default, is matched to the Name property on type objects or the Name key in a hashtable. When piping a hashtable, it is best to use the hashtable's GetEnumerator() method so the objects in the hashtable are actually sent in serial There is a behavior to make note of when passing the type to the Type parameter: A type object can be piped in as a literal (surrounded by []), but cannot be supplied to the Type parameter as a literal. Instead, a string must be passed or cast to a type object before passing (using parentheses). This behavior does not affect input when the type is previously stored in a variable. See the examples for additional clarification. .PARAMETER Type The type to create an accelerator for. Only use the surrounding square brackets in pipeline input. See the examples. .PARAMETER Name The name of the accelerator to use between square brackets. By default, this will be taken from the type object's Name property. .PARAMETER PassThru Causes the command to output the KeyValuePair object representing the added type accelerator. .INPUTS System.Type You can pipe System.Type objects to Add-TypeAccelerator System.String You can pipe type names as System.String to be converted to System.Type System.Collections.Hashtable You can pipe hashtables in the format of @{<AcceleratorName> = <Type to reference>} .OUTPUTS None or System.Collections.Generic.KeyValuePair[[String],[Type]] Using the PassThru parameter, Add-TypeAccelerator returns a KeyValuePair object that represents the new type accelerator entry. Otherwise, there is no output. .EXAMPLE 'System.Collections.BitArray' | Add-TypeAccelerator This command will add the accelerator [BitArray] to the session for the type [System.Collections.BitArray]. The Name for the accelerator comes from the type objects's Name property. .EXAMPLE Add-TypeAccelerator -Name AL -Type System.Collections.ArrayList This command will add the accelerator [AL] to the session for the type [System.Collections.ArrayList]. Note the lack of square brackets surrounding the type. .EXAMPLE [System.Collections.ArrayList] | Add-TypeAccelerator This command will add the accelerator [ArrayList] to the session for the type [System.Collections.ArrayList]. Note the use of square brackets surrounding the type. .EXAMPLE @{AList=[System.Collectons.ArrayList]; BitA='System.Collections.BitArray'} | Add-TypeAccelerator This command will add the accelerators [AList] and [BitA] to the session for the types [System.Collections.ArrayList] and System.Collections.BitArray, respectively. .NOTES This script is based on the funciton found at http://poshcode.org/1869, but had to be updated to accomodate a change made in PowerShell 3.0/4.0. Author: Chris Carter Version: 1.6 .LINK http://poshcode.org/1869 #> #Requires -Version 2.0 [CmdletBinding(SupportsShouldProcess=$true)] Param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$true,ParameterSetName="TypeOrString")] [String]$Name, [Parameter(Mandatory=$true,Position=1,ValueFromPipeline=$true,ParameterSetName="TypeOrString")] [Object[]]$Type, [Switch]$PassThru ) Begin { Function WarnFor-CurrentReference ($AcceleratorName, $AcceleratorType) { $warnTitle = "Warning: Accelerator [$AcceleratorName] Already Exists" $warnMessage = "[$AcceleratorName] already exists and references type [$($accel::Get[$AcceleratorName].FullName)]. Proceeding will overwrite the current reference to [$($AcceleratorType.FullName)].`nDo you want to proceed?" $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Overwrites the current accelerator reference with the new reference." $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Leaves the current accelerator reference in place." $choices = [System.Management.Automation.Host.ChoiceDescription[]]($yes,$no) $host.UI.PromptForChoice($warnTitle, $warnMessage, $choices, 1) } Function PSv5Patch { $builtinField = $accel.GetField("builtinTypeAccelerators", [System.Reflection.BindingFlags]"Static,NonPublic") $builtinField.SetValue($builtinField, $accel::Get) } Function Add-TypeAccelerator ($Name, $Type) { $keepIntact = 0 switch ($true) { {$Type -is [System.Collections.DictionaryEntry]} {$Name = $Type.Name; $Type = $Type.Value} {$Type -is [String]} {$Type = [Type]$Type} {!$Name} {$Name = $Type.Name} {$accel::Get.Keys -contains $Name} {$keepIntact = WarnFor-CurrentReference $Name $Type} {!$keepIntact} {if ($PSCmdlet.ShouldProcess("$($Type.FullName)", "Add [$Name] accelerator")) { $accel::Add($Name, $Type) if ($PSVersionTable.PSVersion.Major -eq 5) {PSv5Patch} }} } if ($PassThru) {Get-TypeAccelerator -Name $Name;} } } Process { foreach($rt in $Type) { if ($rt -is [Hashtable]) { foreach ($object in $rt.GetEnumerator()) { Add-TypeAccelerator -Type $object } } else {Add-TypeAccelerator $Name $rt} } } } Function Remove-TypeAccelerator { <# .SYNOPSIS Removes type accelerators from the PowerShell session. .DESCRIPTION Remove-TypeAccelerator removes type accelerators from the the PowerShell session. Type accelerators are shortened names for types, such as [switch] for [System.Management.Automation.SwitchParameter]. Either the name of an accelerator (without brackets) or types referenced by accelerators may be piped in. If a type has multiple accelerators, passing that type will remove all of its accelerators. There is a behavior to make note of when passing the type to the Type parameter: If the type is piped in it must be surrounded by square brackets, but if supplied by name or position, it cannot be surrounded by square brackets. This behvior does not affect input when the type is previously stored in a variable. See the examples for additional clarification. .PARAMETER Name The name of the accelerator to remove without the squre brackets. .PARAMETER Type The type whose acclerators will be removed. Only use the surrounding square brackets in pipeline input. See the examples. .PARAMETER InputObject This parameter is used in the pipeline when accepting objects from other commands in the module. .INPUTS System.Type You can pipe System.Type to Remove-TypeAccelerator System.String You can pipe System.String to Remove-TypeAccelerator. .OUTPUTS None Remove-TypeAccelerator does not produce any output. .EXAMPLE Remove-TypeAccelerator -Name ArrayList This command will remove the accelerator [ArrayList] from the session for the type [System.Collections.ArrayList]. .EXAMPLE [System.Collections.ArrayList] | Remove-TypeAccelerator This command will remove the accelerator [ArrayList] from the session for the type [System.Collections.ArrayList]. Note the use of square brackets surrounding the type. .NOTES This script is based on the funciton found at http://poshcode.org/1869, but had to be updated to accomodate a change made in PowerShell 3.0/4.0. Author: Chris Carter Version: 1.5 .LINK http://poshcode.org/1869 #> #Requires -Version 2.0 [CmdletBinding(SupportsShouldProcess=$true,DefaultParameterSetName="Name")] Param( [Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true,ParameterSetName="Name")] [String[]]$Name, [Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true,ParameterSetName="Type")] [Type[]]$Type, [Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="KeyValue")] [System.Collections.Generic.KeyValuePair[String,Type]]$InputObject ) Process { $Collection = $Name, $Type, $InputObject | Where-Object {$_} foreach ($object in $Collection) { $hits = @() if ($object -is [KVPair]) { $hits += $object } else {$hits += Get-TypeAccelerator $object} $result = $hits | ForEach-Object { if ($PSCmdlet.ShouldProcess("System.Management.Automation.TypeAccelerators", "Remove [$($_.Key)] accelerator")) { $accel::Remove($_.Key) } } } } } Function Rename-TypeAccelerator { <# .SYNOPSIS Renames type accelerators in the PowerShell session. .DESCRIPTION Rename-TypeAccelerator renames type accelerators in the the PowerShell session. Type accelerators are shortened names for types, such as [switch] for [System.Management.Automation.SwitchParameter]. Either the name of an accelerator (without brackets) or a KeyValuePair object representing its entry in the type accelerators dictionary may be piped in. A scriptblock may be passed to the NewName parameter while in the pipeline to rename multiple accelerators using the -replace operator. See the examples for details. There is a behavior to make note of when passing the type to the Type parameter: If the type is piped in it must be surrounded by square brackets, but if supplied by name or position, it cannot be surrounded by square brackets. This behvior does not affect input when the type is previously stored in a variable. See the examples for additional clarification. .PARAMETER Name The name of the accelerator to rename without the squre brackets. .PARAMETER InputObject This parameter is used in the pipeline when accepting objects from other commands in the module. .PARAMETER PassThru Causes the command to output an object representing the renamed entry in the type accelerators dictionary .INPUTS System.Collections.Generic.KeyValuePair[String,Type] You can pipe KeyValuePair object to Rename-TypeAccelerator that represent the accelerators entry in the dictionary. System.String You can pipe String objects representing the name of a type accelerator (without bracketss) to Rename-TypeAccelerator. .OUTPUTS None or a KeyValuePair object representing the renamed type accelerator dictionary entry. .EXAMPLE Rename-TypeAccelerator -Name List -NewName AList This command will rename the accelerator [List] to [Alist]]. .EXAMPLE Get-TypeAccelerator List | Rename-TypeAccelerator -NewName Alist This command will rename the retrieve the entry for [List] then pipe it to Rename-TypeAccelerator to be renamed to [AList] .EXAMPLE $NamesOfAccelerators | Rename-TypeAccelerator -NewName {$_ -replace '^', 'PS'} This command will rename all of the accelerators with names that are stored in the variable by inserting the characters 'PS' at the beginning of each name. .EXAMPLE Get-TypeAccelerator System.Collections.ArrayList | Rename-TypeAccelerator -NewName {$_.Key -replace '^', 'AL'} This command will rename all of the accelerators that reference the ArrayList class by inserting the characters 'AL' at the begnning of each name. .NOTES This script is based on the funciton found at http://poshcode.org/1869, but had to be updated to accomodate a change made in PowerShell 3.0/4.0. Author: Chris Carter Version: 1.0 .LINK http://poshcode.org/1869 #> #Requires -Version 2.0 [CmdletBinding(SupportsShouldProcess=$true,DefaultParameterSetName="Name")] Param( [Parameter(Mandatory=$true,Position=0,ParameterSetName="Name")] [String]$Name, [Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="KeyValue")] [Object]$InputObject, [Parameter(Mandatory=$true,Position=1,ParameterSetName="Name")] [Parameter(Mandatory=$true,Position=0,ParameterSetName="KeyValue")] [String]$NewName, [Switch]$PassThru ) Begin { if ($NewName -match '.*\s-replace\s.*') { try { $scriptblock = [Scriptblock]::Create($NewName) if ($PSCmdlet.ParameterSetName -eq 'Name') { Write-Error "A scriptblock is only accepted in the pipeline." exit } } catch {Write-Error $_; exit} } } Process { $object = $Name, $InputObject | Where-Object {$_} if ($scriptblock) { try {$NewName = & $scriptblock} catch {Write-Error $_; continue} } if ($object -is [KVPair] -or $object -is [String]) { if ($object -is [String]) { $object = Get-TypeAccelerator $object if (!$object) {continue} } if ($PSCmdlet.ShouldProcess("System.Management.Automation.TypeAccelerators", "Rename [$($_.Key)] accelerator to [$NewName]")) { Add-TypeAccelerator -Name $NewName -Type $object.Value -PassThru:$PassThru -Confirm:$false if ($accel::Get[$NewName]) { Remove-TypeAccelerator -Name $object.Key -Confirm:$false } } } else {Write-Error "The value passed in the pipeline is not a KeyValuePair or String object"} } } $accel = [PowerShell].Assembly.GetType("System.Management.Automation.TypeAccelerators") $accel::Add('TADict','System.Collections.Generic.Dictionary[String,Type]') $accel::Add('KVPair','System.Collections.Generic.KeyValuePair[String,Type]') $MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = { [void]$accel::Remove('TADict') [void]$accel::Remove('KVPair') } New-Alias -Name gta -Value Get-TypeAccelerator New-Alias -Name ata -Value Add-TypeAccelerator New-Alias -Name rta -Value Remove-TypeAccelerator New-Alias -Name rnta -Value Rename-TypeAccelerator |