Recently there was a discussion between community experts and a product team about a module they are working on. The topic being discussed was cmdlet aliases: whether or not they should provide aliases for their cmdlets out of the box and if so, how they should be provided. Aliases are great for ad-hoc PowerShell work, which is what most PowerShell users do at this point, and incredibly useful when you’re trying to put out a fire and managing your infrastructure using PowerShell. However, there are many important things that module authors need to consider when planning aliases for their cmdlets, as follows:
1. There are many cmdlets out now, and more and more every month. Coming up with a vsa (very short alias) that is unique is a challenge at best, and the more time goes by the more tla’s (three-letter aliases) will get used up. The likelihood of an alias conflict is already high, and increasing all the time given the number of commands that are available both from Microsoft and from third party vendors.
2. The land grab with alias names is worse than it is with functions or cmdlets. With functions or cmdlets, you can have multiple modules loaded with conflicting names and access either command using the fully qualified command name. With aliases though you are not provided this same capability – there can be only one. Aliases are simply commands set to a single value and they cannot be qualified using a module name qualifier to disambiguate if a name conflict arises.
3. Depending on how careful (or not) that developers are, it is very easy for a module author to completely take over (overwrite) an existing alias with no warning or message indicating that this has happened, resulting in potential command hijacking between module teams. A simple call to Set-Alias does this without warning. On the flipside, if developers don’t hijack aliases, then some of the aliases they would otherwise create may simply not be defined.
4. When aliases are hijacked, unloading a module doesn’t correct the problem because an alias that was overwritten by a module alias will simply become completely unavailable when the alias is removed as the module is unloaded.
As far as I am aware, this situation does not improve with the next version of PowerShell either, so it’s years away from getting better.
Believe it or not, even with these things in mind, I’m actually still pro aliases. I just think that some extra care/thought needs to be put into their definition. There is no real standard here that both satisfactorily addresses the issues identified above and that allows for consistency across companies/teams at this time. Given that is the current state of affairs, if you are considering aliases for your module I recommend one of the following approaches:
1. [SAFEST] Rather than trying to come up with something that can be shipped despite these issues, at this time I think aliases would be best addressed in a "tips and tricks" type of blog post, proposing a short script that defines some useful aliases for the module/snapin in question in order to allow admins to be able to deal with fires quickly using ad-hoc PowerShell commands via some aliases. Such a script should generate warnings whenever a name conflict is discovered so that users are aware when an alias either cannot be created or is overwritten.
2. [EXPERIMENTAL] Ship aliases with your module, but try to make sure they really are unique. For example, if you’re a vendor whose company name starts with Q, you could prefix all of your aliases with "q". This is attractive because there are no verbs that start with "q", so right from the start you’ve dramatically reduced the chance that you’ll have a conflict, setting yourselves up better to have aliases that belong to you. Then you would only have to coordinate within your company to make sure the aliases used across teams are unique. This isn’t foolproof though because there may be multiple products/vendors that adopt the same standard, and if the name of your company or product starts with G, the likelihood of a conflict would be much higher (the alias prefix used for "get-*" cmdlets is "g") so you may want to choose a pair of letters instead. Regardless, you’ve likely reduced the risk, and you could generate a warning whenever you run into a conflict that prevents an alias from being created.
3. [RECOMMENDED] Lots of 1 and a little bit of 2: use unique alias names that work for your product team/company, but don’t ship them with the module. Instead, push them out as a value add on a blog post, and see how the community responds. At the same time work with MVPs and Microsoft to get these issues addressed such that a shorthand system for command names does work. Some MVPs, already proposed a few things to the Microsoft PowerShell team that could help here (aliases for module names for one — think PS\gsv for a core PowerShell version of Get-Service or EX\gu for the Get-User cmdlet that comes with the Microsoft Exchange module or AD\gu for the Get-User cmdlet that comes with the Microsoft Active Directory module, and so on), but more discussions need to happen and this will take more time.
I recommend the third option because given the current issues with alias hijacking and with no support for disambiguation, it seems to be the best solution for now (from my perspective at least). If you have come up with other alternatives that resolve these issues, please share them with the community so that this improves going forward.
Hope this helps,
Kirk out.
It’s too bad there’s not a way to generate aliases without exporting them unless the user asks for them. There’s an -Alias parameter on Import-Module, but it’s purpose is to OVERRIDE the aliases that the module attempts to export, rather than overriding the aliases that the module does NOT attempt to export.
One additional possibility though, is to ship whatever aliases you like, but wrapped in code such that the user has to explicitly opt-in to exporting them:
Import-Module ModuleName -Argument ExportAliases
You could alternatively include a function in your module to explicitly define the aliases on demand. Still, I think aliases should be used at a minimum, for the most frequent use cases only.
I’d be interested in seeing usage counts that show how frequently the core aliases are used. Obviously the domain-specific ones are used the most, but others I suspect are hardly used at all, in which case why have aliases for those at all? You can tell by the core aliases that some were created simply because the developer and tester working on that set of commands wanted to have aliases for their simplified use, even when they aren’t really necessary in the real world (like the *-Alias commands — who needs aliases for Import-Alias and Export-Alias? I’d wager those aliases are hardly used at all.)
[…] question came up about the behavior of Import-Module (in the context of this interesting discussion of whether module authors should provide aliases), especially with Version 3 and the auto-loading of modules (what’s […]
I don’t think that vendors should create aliases at all. Aliases are shortcuts that makes commands more accessible by not requiring you to type long names for frequently used commands. They should never be in published scripts and they should never be used in examples.
The builtin aliases are ok in my opinion because they do serve as a way to ease the transition for users to PowerShell, e.x. dir or cd.
Let the user decide what they want shortened and create their own aliases.
I agree that aliases should never show up in published scripts or examples. I don’t agree that vendors shouldn’t create aliases at all though. I would state it differently: that vendors should only include aliases when existing knowledge of a shorthand command vocabulary makes it extremely advantageous, or when the frequency that commands are used warrants it. For the former, examples in core PowerShell commands are abundant: dir, cd, mkdir, etc. For the latter, there are some good examples that are used quite frequently (and therefore are big time savers).
Consider imo/rmo for Import-/Remove-Module…those two save me personally a ton of time (they’re much less important in PowerShell v3 though). Or consider common ones like gsv (Get-Service), gps (Get-Process), or the breakpoint aliases: gbp, sbp, rbp, all very useful when defining command or variable breakpoints. They’re also useful for line breakpoints, but less since modern scripting environments make line breakpoints easy. If these aliases weren’t defined by default, I’d have to be diligent and organized enough to set up a profile, or a USB key if I work with multiple machines, plus consider RDP scenarios where a USB key wouldn’t be helpful. With those challenges in mind, I’m all for having some aliases defined by default…I just think module authors need to take it easy and stick to the most useful and most frequent commands for this.
I won’t argue with you there. I will give the PowerShell team great leeway in this because this is the base system and these are aliases for the core. I don’t think that other vendors or product teams within Microsoft should be creating aliases. They can recommend aliases all they want, just don’t create them as part as their product.
[…] it is helpful. There is some discussion as to whether this is best practice. I recommend reading Kirk Munro’s post on the topic. Always make sure that another alias does not conflict with the one you are […]
I can’t recall where I read it, but as an ISV module developer, it’s helpful to provide aliases for cmdlets in order to reconcile the terminology of the product being exposed via the module with PowerShell’s prescriptive verbs. If the aliases conform to the same recommended convention for cmdlet names (i.e. -), it decreases the likelihood of name clashes.
For example, say a product’s users are accustomed to the notion of “holding” a job. “Hold” isn’t one of the PowerShell standard verbs, but “suspend” is.
In order to reconcile this, assuming the two-letter product abbreviation is “BE”, the ISV could export a cmdlet called Suspend-BEJob and an alias to the cmdlet called Hold-BEJob.
The result is that users benefit from the consistency and usability of both the PowerShell verbs AND product-specific terminology.
Hi Rafael,
I agree with supporting a familiar vocabulary using aliases, however I probably wouldn’t create them with a cmdlet-like “verb-noun” name format because I’d be afraid users would use those aliases in published and shared scripts and not just in ad-hoc work. In this specific case, I think the consistency provided through a small library of verbs which benefits the entire PowerShell community outweighs the benefits you’d be providing to scripters by using aliases to add verb substitutes for domain vocabulary familiarity. Learning that PowerShell has only a finite set of verbs and figuring out how to make intelligent guesses using synonyms once you learn some of those verbs is only a small hurdle to overcome. Otherwise, if one team uses Hold as an alias verb for Suspend and another uses Pause, and yet another uses Delay, or Retain, or something else, then we lose the benefits that a small set of verbs provides. Besides, there really is no notion of verbs in aliases as far as command metadata is concerned, so users wouldn’t be able to invoke Get-Command -Verb Hold to discover your alias commands, which could cause further confusion.
Even though I say all that though, I think aliases are great at retaining domain knowledge. Maybe not so much in the verb-noun format though. But I’m always open to discussion to see what possibilities do come out of it, and this is only my opinion on this issue. Food for thought anyway.
Kirk out.
[…] question came up about the behavior of Import-Module (in the context of this interesting discussion of whether module authors should provide aliases), especially with Version 3 and the auto-loading of modules (what’s […]
I’m a bit late to this party, but my thoughts are fairly simple:
Get rid of *all* aliases.
That’s right, all of them. Everything from GCI to CD to the most loathsome of them all: % and ?
I am so fed up of modules not importing because they are fighting over aliases like divercees fighting over their children.
Aliases have no place in core PowerShell and any modules published to the PS Gallery.
I’m very curious: what modules fail to import because of their aliases? Personally I like core command aliases, including ? and %, but excluding aliases that hide Linux commands (ls, man, etc)…they save me a lot of typing.
Currently Hyper-V, VirtualMachineManager and PowerCLI have made me blow a gasket.
But I have hated Aliases long enough to put this in my PS Profile:
$Aliases = (Get-Alias|Select-Object -ExpandProperty Name)
$Aliases | ForEach {Try {Remove-Item -Path Alias:$_ -ErrorAction SilentlyContinue}Catch{}}
It frustrates and annoys me that I can’t remove ? and % using this method…
That I have to run it after importing modules is just unacceptable. I really don’t think there is any excuse for keeping aliases as part of core PowerShell. Anyone who wants an alias can create it themselves quite easily.
That’s good feedback. Maybe PowerShell.exe should include a -NoAliases switch to disable that functionality altogether. It would be worthwhile to have this discussion on the Issues page of https://github.com/PowerShell/PowerShell.
Regarding your script, you can replace it with this:
Remove-Item -Path Alias:* -Force
That will get rid of all aliases, no exceptions.
I forgot to say thanks for that one liner to get rid of even ? and %.
And yes, a -noalias switch would be useful, for me at least 😀