Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I override a Powershell native cmdlet but call it from my override

Tags:

powershell

In Javascript it is possible to do so, I think. In Powershell I'm not sure how to :

Let's say I want to override every call to write-host with my custom method but at some time I want to execute the native write-host inside my overide. Is it possible to store the native implentation under another name so as to call it later from new implementation ?

Update : it seems to me that the answer https://serverfault.com/a/642299/236470 does not fully answer the second part of my question. How do I store and call the native implementation ?

like image 344
user310291 Avatar asked Nov 17 '15 00:11

user310291


People also ask

How do I run a cmdlet in PowerShell?

Run an old-fashioned command line (cmd.exe), type powershell and execute. Or, you can hit the PowerShell icon on the taskbar. Either way, you'll get a ready-to-use Windows PowerShell console. Use “Get-Help” cmdlet from before as a starting point for your journey.

What is the default confirm preference setting in PowerShell?

Because most cmdlets and functions use the default risk value, ConfirmImpact, of Medium, and the default value of $ConfirmPreference is High, automatic confirmation rarely occurs. However, you can activate automatic confirmation by changing the value of $ConfirmPreference to Medium or Low.

Is cmdlet a command in PowerShell?

A cmdlet -- pronounced command-let -- is a small, lightweight command that is used in the Windows PowerShell environment. A cmdlet typically exists as a small script that is intended to perform a single specific function such as coping files and changing directories.

How do I get the PowerShell cmdlet?

The Get-Command cmdlet gets all commands that are installed on the computer, including cmdlets, aliases, functions, filters, scripts, and applications. Get-Command gets the commands from PowerShell modules and commands that were imported from other sessions.


2 Answers

Calls to functions will override cmdlets. You can read more on this from about_Command_Precedence on TechNet ...

If you do not specify a path, Windows PowerShell uses the following precedence order when it runs commands:

  1. Alias
  2. Function
  3. Cmdlet
  4. Native Windows commands

So simply making a function of the same name as a native cmdlet will get you what you want.

function Write-Host{
    [cmdletbinding()]
    param(
        [Parameter(Mandatory,ValueFromPipeline)]
        $string
    )
    Process {
        # Executes once for each pipeline object
        If ($string -match "bagels"){
            Microsoft.PowerShell.Utility\Write-Host $string -ForegroundColor Green
        }else{
            Microsoft.PowerShell.Utility\Write-Host $string
        }
    }
}

So now write-host works with pipeline input that we can filter with. Calling the "real" cmdlet is as easy as specifying the module in the call. You can see I have done that twice in the above code sample. Some sample usage and output would be the following:

enter image description here

Be careful that you don't forget you have done this if you save it in a profile or something of that nature. Use Get-Command Write-Host whenever in doubt. In my case you can remove the override by calling Remove-Item function:write-host

You can also look into what are called proxy functions but I think that is overkill for what you intend to do.

like image 98
Matt Avatar answered Oct 03 '22 19:10

Matt


Yes you can. I have an answer for that here on ServerFault, but since it's a different site I'll copy it since I can't close as duplicate to another site.


Yes, you can override Get-ChildItem or any other cmdlet in Powershell.

Name Your Function The Same

If you make a function with the same name in the same scope, yours will be used.

Example:

Function Get-ChildItem {
[CmdletBinding()]
param(
    # Simulate the parameters here
)
    # ... do stuff
}

Using Aliases

Create your own function, and then create an alias to that function, with the same name as the cmdlet you want to override.

Example:

Function My-GetChildItem {
[CmdletBinding()]
param(
    # Simulate the parameters here
)
    # ... do stuff
}

New-Alias -Name 'Get-ChildItem' -Value 'My-GetChildItem' -Scope Global

This way is nice because it's easier to test your function without stomping on the built-in function, and you can control when the cmdlet is overridden or not within your code.

To remove the alias:

Remove-Item 'Alias:\Get-ChildItem' -Force
like image 35
briantist Avatar answered Oct 03 '22 21:10

briantist