1

I want to extend the functionality of cd but retain all of the existing parameters of Set-Location. So I created a function go which does a bunch of additional stuff and then aliased cd to it (I had to use -Option AllScope to get this to work, does anyone know why I can't just re-alias cd without using that?)

Set-Alias cd go -Option AllScope

The problem is that I would like go to do certain things, but to also failover to Set-Location functionality whenever a standard Set-Location switch is invoked:

Set-Location -LiteralPath <String> [-PassThru] [-UseTransaction] [<CommonParameters>]

Set-Location [[-Path] <String>] [-PassThru] [-UseTransaction] [<CommonParameters>]

Set-Location [-PassThru] [-StackName <String>] [-UseTransaction] [<CommonParameters>]

Looking for advice in extending the functionality of a built-in Cmdlet by creating a secondary function and then re-using a built-in alias in this way? i.e. I want cd to continue to do all of the Set-Location functionality, except when new switches that I want are applied to the secondary function that it is now aliased to?

YorSubs
  • 3,194
  • 7
  • 37
  • 60

2 Answers2

1

its called proxy function see blog post

MikeSh
  • 352
  • 1
  • 5
  • Thanks Mike, I've read through that, really useful. Marked other Mike as the answer as he linked to quite a useful example and on the `-Scope` point. Cheers. – YorSubs Mar 02 '20 at 13:53
1

As MikeSh helpfully advises, a proxy function (wrapper function) is the way to go:

  • Create your go function as a proxy (wrapper) function (or script) for the Set-Location cmdlet, as demonstrated in this answer.

  • Add your custom functionality directly to this wrapper function.

go is then the single function that provides both Set-Location functionality and the desired custom functionality, so Set-Alias cd go -Option AllScope is sufficient.

Important: Since you're modifying a built-in, session-wide alias, be sure that your go function is a true superset of Set-Location's functionality; that is, make sure that it neither modifies nor restricts the original behavior - otherwise, third-party code may malfunction.


I had to use -Option AllScope to get this to work, does anyone know why I can't just re-alias cd without using that?

The built in alias cd is defined with -Option AllScope; any alias defined this way can only be modified if
-Option AllScope is again specified on redefinition with Set-Alias.

The reason is that -Option AllScope means that the alias is automatically present in any scope, which effectively means that the specified definition applies session-wide.

Without -Option AllScope, Set-Alias creates / modifies an alias in a single scope only - which is either the current scope by default, or the one targeted via the optional -Scope parameter - though all descendant scopes of that scope see the definition too.

This contradicts a preexisting -Option AllScope definition for a given alias name, so PowerShell gives you two options to resolve the contradiction:

  • Modify the existing AllScope definition, which you must signal by specifying -Option AllScope as part of the redefinition, which obviously means that you're modifying the session-wide definition of the alias.

  • Delete the preexisting AllScope definition with Remove-Alias (which is not advisable, especially with built-in aliases), which then allows you to create a scope-specific alias (by omitting -Option AllScope).

Note that if you create an alias without -Option AllScope, but in the global scope (e.g., via your $PROFILE file or with -Scope Global), the effect is similar to -Option AllScope, given that descendant scopes see the definition too and given that all scopes are descendants of the global scope (including modules)[1].

However, any descendant scope can override the global definition.


[1] It is technically possible to create scopes not linked to the global scope, but that option is little-known and rarely used in practice.

mklement0
  • 382,024
  • 64
  • 607
  • 775