Finding What’s Been Added to PowerShell

Jeffrey did a nice little write-up titled Detecting Conflicts between Aliases, Functions, and Cmdlets over on the PowerShell team blog.  We devised some scripts for PSCX 1.1 to help with a similar problem.  That is, when you have six or so distributed developers contributing to an open source project like PSCX, it can be hard to track down what all the new cmdlets, filters, functions, aliases and scripts are.  Well the beautiful thing about PowerShell is all the rich metadata that you can get about the environment.  With this information and just a wee bit of PowerShell script we were able to fully discover all the new functionality that had been added to PowerShell.  Here’s the basic steps we took.  Note the big guns here are Get-Command and Compare-Object:
  1. Fire-up PowerShell with the -NoProfile option (ideally you would do this before installing PSCX or any other add-on) and execute:

    $orig = gcm -type Alias, Function, Filter, Cmdlet, ExternalScript | Sort CommandType, Name

  2. Install an add-on like PSCX 1.1 and execute the same query again but stash the results in a different variable:

    $new = gcm -type Alias, Function, Filter, Cmdlet, ExternalScript | Sort CommandType, Name

  3. Now compare the two:

    Compare-Object $orig $new -property Name,CommandType -sync 1000 | sort CommandType, Name

Note that the Side Indicator column shows whether the item was added or deleted. Now that’s pretty cool as it stands but the output isn’t that pretty.  Take a look at this script which we used for PSCX 1.1:
 
param(
 [string]$refPath = ‘Pscx1_0Commands.xml’,
 [string]$diffPath = ‘Pscx1_1Commands.xml’
)
function Remove-Aliases($cmdal) {
 $script:aliases = $($script:aliases |? {
  $cmdal -notcontains $_.Name
 })
}
function Get-CommandNoun($command) {
 $command.Split(‘-‘, 2)[1]
}
function Get-AliasCommand($al) {
 $diff |? { $_.Name -eq $al } |% { $_.ResolvedCommand.Name }
}
function Get-CommandAliasNames($command) {
 $diff |? { $_.ResolvedCommand.Name -eq $command } |% { $_.Name }
}
function Format-CommandAliases($cmdal) {
 $result = ”
 $OFS = ‘, ‘
 if ($cmdal) {
  $result += ‘ (‘
  $result += "$cmdal"
  $result += ‘)’
 }
 
 $result
}
$ref  = Import-CliXml $refPath | Sort Name
$diff = Import-CliXml $diffPath  | sort Name
$comparisonResult = Compare-Object $ref $diff -property Name,CommandType -sync 1000 | Sort-Object SideIndicator
$changes = $comparisonResult | Group-Object CommandType
$script:aliases   = $null
$script:cmdlets   = $null
$script:filters   = $null
$script:functions = $null
$script:scripts   = $null
$IsNew     = { $_.SideIndicator -eq ‘=>’ }
$IsRemoved = { $_.SideIndicator -eq ‘<=’ }
$changes |% {
 if ($_.Name -eq ‘Alias’)          { $aliases   = @($_.Group) }
 if ($_.Name -eq ‘Cmdlet’)         { $cmdlets   = @($_.Group) }
 if ($_.Name -eq ‘Filter’)         { $filters   = @($_.Group) }
 if ($_.Name -eq ‘Function’)       { $functions = @($_.Group) }
 if ($_.Name -eq ‘ExternalScript’) { $scripts   = @($_.Group) }
}
""
"NEW CMDLETS"
$cmdlets | ? $IsNew | Sort { Get-CommandNoun $_.Name } | %{
 $cmdname = $_.Name
 $result = "    $cmdname"
 
 $cmdal = @(Get-CommandAliasNames $cmdname)
 $result += Format-CommandAliases $cmdal
 Remove-Aliases $cmdal
 $result
}
""
"NEW FUNCTIONS AND FILTERS"
@($functions + $filters) | ? $IsNew | Sort Name | %{
 $name = $_.Name
 $result = "    $name"
 
 $cmdal = @(Get-CommandAliasNames $name)
 $result += Format-CommandAliases $cmdal
 
 Remove-Aliases $cmdal
 
 $result
}
""
"NEW SCRIPTS:"
$scripts | ? $IsNew | Sort Name | %{
 $name = $_.Name
 $result = "    $name"
 
 $cmdal = @(Get-CommandAliasNames $name)
 $result += Format-CommandAliases $cmdal
 
 Remove-Aliases $cmdal
 
 $result
}
""
"NEW ALIASES"
$aliases | ? $IsNew | %{
 "    $($_.Name) ($(Get-AliasCommand $_.Name))"
}
""
"REMOVED STUFF"
$comparisonResult | ? $IsRemoved | Sort Name | %{
 "    $($_.Name)"
}
 
The output looks like this:
 
NEW CMDLETS
    Get-ADObject
    Test-Assembly
    Resolve-Assembly
    ConvertTo-Base64 (cvtb64)
    ConvertFrom-Base64 (cvfb64)
    Import-Bitmap
    Resize-Bitmap
    Export-Bitmap
    Format-Byte
    Write-BZip2
    Write-Clipboard
    Get-Clipboard (gcb)
    Set-Clipboard
    Out-Clipboard (ocb)
    Get-DhcpServer
    Get-DomainController
    Set-FileTime (touch)
    Get-FileVersionInfo (gfvi)
    Get-ForegroundWindow
    Set-ForegroundWindow
    Write-GZip
    New-Hardlink (ln)
    Get-Hash
    Format-Hex (fhex)
    Ping-Host (ping)
    Resolve-Host
    New-Junction
    ConvertTo-MacOs9LineEnding
    Remove-MountPoint
    Get-MountPoint
    Get-PEHeader
    Get-Privilege
    Set-Privilege
    Start-Process (saps, start)
    Get-PSSnapinHelp
    Get-Random (rnd)
    Get-ReparsePoint
    Remove-ReparsePoint
    New-Shortcut
    Get-ShortPath (gsp)
    Send-SmtpMail (mail)
    Split-String
    Join-String
    New-Symlink
    Get-TabExpansion
    Start-TabExpansion
    Write-Tar
    Stop-TerminalSession
    Get-TerminalSession
    Disconnect-TerminalSession
    ConvertTo-UnixLineEnding
    Set-VolumeLabel
    ConvertTo-WindowsLineEnding
    Format-Xml (fxml)
    Select-Xml (sxml)
    Convert-Xml (cvxml)
    Test-Xml
    Write-Zip

NEW FUNCTIONS AND FILTERS
    Add-PathVariable (apv)
    cd
    cd-
    cd..
    cd…
    cd….
    cd…..
    cd?
    cd\
    cd~
    cd+
    dird
    dirs
    dirt
    dirw
    dirx
    Disable-Breakpoints (dbp)
    Edit-File (e)
    Edit-GlobalHostProfile (eghp)
    Edit-GlobalProfile (egp)
    Edit-HostProfile (ehp)
    Edit-Profile (ep)
    Enable-Breakpoints (ebp)
    Get-CallStack (gcs)
    Get-ExceptionForHR (hrexc)
    Get-ExceptionForWin32 (winexc)
    Get-PropertyValue (gpv)
    Get-PscxAlias (galpscx)
    Get-PscxCmdlet (gcmpscx)
    Get-PscxDrive (gdrpscx)
    Get-PscxVariable (gvpscx)
    Get-VariableSorted (gvs)
    glp
    Invoke-NullCoalescing (??)
    Invoke-Ternary (?:)
    less (pager)
    New-HashObject (nho)
    Quote-List (ql)
    Quote-String (qs)
    Remove-Accessors (ra)
    Set-Breakpoint (bp)
    Skip-Breakpoints (skbp)
    Start-EyeCandy
    Test-PscxPreference
    Update-HostTitle
    Update-Profile (rehash, up)
    Write-Prompt

NEW SCRIPTS:
    Add-DirectoryLength.ps1 (adl)
    Add-ShortPath.ps1 (asp)
    Clip.ps1
    Connect-VirtualServer.ps1 (vmadmin)
    ConvertFrom-WmiDateTime.ps1
    ConvertFrom-WmiTimeSpan.ps1
    ConvertTo-DmtfDateTime.ps1
    ConvertTo-DmtfTimeInterval.ps1
    Export-History.ps1 (ephy)
    Get-DiskUsage.ps1
    Get-HelpMatch.ps1 (apropos, ghm)
    Get-LoremIpsum.ps1 (lorem)
    Get-PagedHelp.ps1 (help, man)
    Get-ScreenCss.ps1
    Get-ScreenHtml.ps1
    Get-TypeName.ps1 (gtn)
    Get-Url.ps1
    Import-Assembly.ps1 (ipasm)
    Import-History.ps1 (iphy)
    Reduce-Object.ps1 (reduce)
    Resolve-Error.ps1 (rver)
    Search-Transcript.ps1 (srts)
    Select-History.ps1
    Set-ReadOnly.ps1 (sro)
    Set-Writable.ps1 (swr)

NEW ALIASES
    measure (Measure-Object)
    new (New-Object)
    ss (Select-String)

REMOVED STUFF
    cd

 
Advertisements
This entry was posted in PowerShell. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s