Fun with Script Cmdlets

 


Script Cmdlets are one of the coolest things about the newer version of PowerShell.  A Script cmdlet allows you to use all of the variety of cmdlet parameter sets inside of PowerShell functions.


Since Script Cmdlets are PowerShell functions, and the PowerShell engine prefers to run functions rather than commands, you can use Script Cmdlets to override an existing cmdlet.  You might want to do this to add or remove parameters from a cmdlet you use often.  Also, you might just want to see what a cmdlet’s parameters look like in a script cmdlet, so you can go write your own.


Luckily, Powershell  has a way to generate script cmdlets from an existing cmdlet.  Below is a script cmdlet, called New-ScriptCmdlet, that I’ll use to create other script cmdlets.


You can use this to create new script cmdlets from existing cmdlets in a couple of different ways:


# Create a new PowerShell cmdlet from an existing cmdlet


Get-Command Get-Command | New-ScriptCmdlet Get-Command  | Set-Content Get-Command.ps1


# Create a new PowerShell cmdlet from an existing cmdlet’s type


[Microsoft.PowerShell.Commands.GetProcessCommand] | New-ScriptCmdlet Get-Process | Set-Content Get-Process.ps1


# Creates a new PowerShell cmdlet from a random existing command and puts it into a file of the same name


 Get-Command | Get-Random | Foreach-Object {
    $cmdlet = $_
    $scriptCmdlet  = $cmdlet | New-ScriptCmdlet $cmdlet.Name
    $scriptCmdlet | Set-Content “$($cmdlet.Name).ps1”
}


Hope this helps,



James Brundage [MSFT]


function New-ScriptCmdlet()


{


cmdlet `


 -DefaultParameterSet Type


    param(


    [Parameter(ParameterSetName=”Type”,ValueFromPipeline=$true,Position=1)]


    [Type]


    $type,


   


    [Parameter(ParameterSetName=”CommandInfo”,ValueFromPipeline=$true,Position=1)]


    [Management.Automation.CmdletInfo]


    $commandInfo,


 


    [Parameter(Position=0)]


    [string]


    $name


    )


 


    Process


    {


        if (! $type) {


            if ($commandInfo.ImplementingType) { $type = $commandInfo.ImplementingType }


        }


 


        if ((! $type) -and (! $commandInfo)) {


@”


$(if ($name) { ‘function ‘ + $name + ‘() {‘ })


cmdlet `


param()


begin {}


process {}


end {}


$(if ($name) {‘}’ })


“@              


        } else {


            if (! ($type.IsSubclassOf([Management.Automation.Cmdlet]))) {


                throw “Must provide a cmdlet to create a proxy”           


            }


            $commandMetaData = New-Object Management.Automation.CommandMetadata $type


            $proxyCommand =                                


@”


$(if ($name) { ‘function ‘ + $name + ‘() {‘ })


$([Management.Automation.ProxyCommand]::Create($commandMetaData))


$(if ($name) {‘}’ })


“@


            $executionContext.InvokeCommand.NewScriptBlock($proxyCommand)                         


        }


    }


}