30

I can remove an alias like so:

Remove-Item Alias:wget

Then trying the alias gives the expected result:

PS > wget
wget : The term 'wget' is not recognized as the name of a cmdlet, function,
script file, or operable program.

However, if I put the same into a script,

PS > cat wget.ps1
Remove-Item Alias:wget
wget

it gives unexpected result

cmdlet Invoke-WebRequest at command pipeline position 1
Supply values for the following parameters:
Uri:
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zombo
  • 1
  • 62
  • 391
  • 407
  • This behavior seems to be consistent for all default aliases. User-defined aliases (for me at least) are able to be removed within a script. – Kohlbrr Jun 22 '14 at 19:23
  • That's really weird, it has to be a scope issue. I'll post back after some more tests. – Jason Morgan Jul 14 '14 at 18:33

4 Answers4

38

The following seems to work

If (Test-Path Alias:wget) {Remove-Item Alias:wget}
If (Test-Path Alias:wget) {Remove-Item Alias:wget}
wget

The first line removes the Script level alias, and the second removes the Global level alias. Note that both need to be tested, because if the Global doesn't exist the Script isn't created.

Also this misbehaves in that it modifies the parent without being dot sourced.

Alternatively you can just dot source your original and that would work

. .\wget.ps1
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Guvante
  • 18,775
  • 1
  • 33
  • 64
12

The reason behind this is scope...

There are four scopes: local, script, private, and global

The rules for variables, functions and aliases say that if they are not defined in the current scope then PowerShell will search the parent scopes.

The default for an alias is set to allscope, which make it visible from any child scopes and also they are inherited into any new child scope (I think that would be a fair definition).

Get-Alias -Name wget | select Name,options

Name  Options

wget  AllScope

Once you remove the alias that is the script scope (scope 0), it will then find the alias from the global/parent scope (scope 1).

When you dot source it, you are just saying to run the script in the calling/global scope in the first place, so you are removing the Global alias by default.

Try these...

E.g #1.


1.1) Remove the alias from the global scope.

    Remove-Item -Path Alias:\wget

1.2) Create a new one (global scope) and make it private.

    New-Alias -Name wget -Value dir -Scope private

1.3) Now the alias is not visible from the nested scope. So try run the script and it will not be found.

E.g #2.


2.1) Remove the alias from the global scope. Remove-Item -Path Alias:\wget

2.2) Create a new one and make it AllScope

    New-Alias -Name wget -Value dir -Option AllScope

2.3) Now run your script and it will work fine (using the new alias dir from the parent scope)

You could try the same with variables as well. They should be easier to demo (and play around with) since you can more easily play with the scope parameter when you use New/Get/Set/Remove -scope 1 or scope 0 OR use the scope modifiers, for example, $global:a.

Get-Command -Noun variable -ParameterName scope
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
BRW
  • 149
  • 4
3

Clearly, some of the other answers are on-track and have identified the fact that the alias is present in several scopes.

But if you're trying to invoke wget.exe rather than Invoke-WebRequest (or wget.ps1 ) in some script, the simplest answer might be to put the ".exe" extension on the command name when you invoke it. That way you don't have to fiddle with the aliases.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Burt_Harris
  • 6,415
  • 2
  • 29
  • 64
1

It looks like when you run the script from the PowerShell console it inherits the alias drive from that session. So if wget is there it works, and if it's not it fails. If instead you run the script in a new process it gets removed normally.

Here's the code I used for my demo:

Remove-Item -Path Alias:\wget -Force
wget
Start-Sleep -Seconds 100

The start-sleep will keep your console from closing immediately. Try running that script in a new process. I used the run prompt and PowerShell itself by typing `powershell.exe -file pathtoscript '

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jason Morgan
  • 1,055
  • 7
  • 10