Is it safe to use ALIASES in scripts?

PowerShell Team

In our newsgroup (Microsoft.Public.Windows.Server.Scripting) , Mark Ayers asked the question:
> Shouldn’t best practice for scripts be full command name?

The answer is YES, NO, and MAYBE.

YES – Full names provide the most readable experience for scripts.  This is very important.  People often throw the rock at Perl saying that it is a “write-only language” meaning that after you write a script, you can’t read it or understand what it does.  We believe that Monad scripts will be widely shared and will be used in environments where it is really important to know exactly what is going on.  As such, script readability has always been a strong focus for us.  This is one of the key reasons why we support both a pithy and verbose invocation model (pithy for high-speed interactive use, verbose for scripting).

NO – Not all aliases are the same.  There are a special class of aliases that are READONLY and ALLSCOPE.  You can find these with the following command:

gal | where {“”+$_.options -match “Readonly” } | ft name, definition, options -auto

Take a look at how regular and predictable these are:

MSH> gal g* | where {“”+$_.options -match “Readonly” } |
ft name, definition, options -auto

Name  Definition               Options
—-  ———-               ——-
gal   get-alias     ReadOnly, AllScope
gc    get-content   ReadOnly, AllScope
gci   get-childitem ReadOnly, AllScope
gcm   get-command   ReadOnly, AllScope
gdr   get-drive     ReadOnly, AllScope
ghy   get-history   ReadOnly, AllScope
gi    get-item      ReadOnly, AllScope
gl    get-location  ReadOnly, AllScope
gm    get-member    ReadOnly, AllScope
gp    get-property  ReadOnly, AllScope
gps   get-process   ReadOnly, AllScope
group group-object  ReadOnly, AllScope
gsv   get-service   ReadOnly, AllScope
gu    get-unique    ReadOnly, AllScope
gv    get-variable  ReadOnly, AllScope

MSH> gal ?v | where {“”+$_.options -match “Readonly” } |
ft name, definition, options -auto

Name Definition                 Options
—- ———-                 ——-
gv   get-variable    ReadOnly, AllScope
nv   new-variable    ReadOnly, AllScope
rv   remove-variable ReadOnly, AllScope
sv   set-variable    ReadOnly, AllScope

MSH> gal n* | where {“”+$_.options -match “Readonly” } |
ft name, definition, options -auto

Name Definition              Options
—- ———-              ——-
nal  new-alias    ReadOnly, AllScope
ndr  new-drive    ReadOnly, AllScope
ni   new-item     ReadOnly, AllScope
nv   new-variable ReadOnly, AllScope

MSH> gal *al | where {“”+$_.options -match “Readonly” } | ft name, definition, options -auto

Name Definition                  Options
—- ———-                  ——-
epal export-alias     ReadOnly, AllScope
gal  get-alias        ReadOnly, AllScope
ilal initialize-alias ReadOnly, AllScope
ipal import-alias     ReadOnly, AllScope
nal  new-alias        ReadOnly, AllScope
sal  set-alias        ReadOnly, AllScope

In previous drops, these aliases where CONSTANT which meant that users could not delete or remove them.  They exist because they are very predictable and pithy short hands for the long names.  We made them constant so that you could feel safe using them in any script and that you could share that script with other people knowing that you were guaranteed that those aliases would exist everywhere and mean the same thing so your scripts would not break.  The community provided strong feedback that MSFT should not ship any CONSTANT aliases so we made them READONLY and ALLSCOPE.  This means that you can remove them (using the -FORCE flag) and create your own definitions but it is strongly discouraged.

So in the end, you are pretty safe using the aliases that are READONLY and CONSTANT.  You might argue that this is less safe then using the full command name.  This would not be correct.  Token resolution works by first expanding aliases then binding to a function, then a cmdlet, lastly as an external executable.  When you type “Get-Process”  – it could have been aliased to any other command or there could be a function with this name. So in the end, the READONLY ALLSCOPE aliases are just about as safe as the full command names.

MAYBE.  The other thing you can do in your script is to set up the aliases you’ll use yourself.  Aliases are scoped so this is generally a safe operation and will not contaminate the users environment.  Let me demonstrate using a one of my favorite functions that I define in my profile file, Start-NewScope and its alias sans 

function Start-NewScope
{
param($Prompt = $null) Write-Host “Starting New Scope”
  if ($Prompt -ne $null)
  {  if ($Prompt -is [ScriptBlock])
     {
       $null = New-Item function:Prompt -Value $Prompt -force
     }else
     {   function Prompt {“$Prompt”}
     }
  }
  $host.EnterNestedPrompt()
}
sal sans Start-NewScope

BTW – every time you enter a nested prompt, $NESTEDPROMPTLEVEL is incremented so I include this information in my prompt:

function prompt
{
“[{0}:{1}]MSH> ” -f $PID, $NestedPromptLevel
}

So watch that as I create and exit new scopes.  I’ll create a new scope, redefine some aliases and then exit the scope and show how those aliases are cleaned up and the old aliases are now in scope.

[3312:0]MSH> gal write |ft name,definition -auto

Name  Definition
—-  ———-
write write-object

[3312:0]MSH> write test
test

# NOW WE START A NEW SCOPE AND REDEFINE WRITE
[3312:0]MSH> sans
Starting New Scope
[3312:1]MSH> sal write write-error
[3312:1]MSH> write test
write test : test
[3312:1]MSH> gal write |ft name,definition -auto

Name  Definition
—-  ———-
write write-error

# NOW WE EXIT THE SCOPE WHICH REMOVES THIS ALIAS
# WHICH NOW REVEALS THE PREVIOUS DEFINITION

[3312:1]MSH> exit
[3312:0]MSH> write test
test
[3312:0]MSH> gal write |ft name,definition -auto

Name  Definition
—-  ———-
write write-object

Enjoy!

Jeffrey Snover
Monad Architect

[Edit: Monad has now been renamed to Windows PowerShell. This script or discussion may require slight adjustments before it applies directly to newer builds.]

PSMDTAG:FAQ: Is it save to use ALIASES in scripts?

PSMDTAG:FAQ: What is the difference between CONSTANT and READONLY?

PSMDTAG:FAQ: Nested Prompt – How do I know if I’m in a nested prompt? $NestedPromptLevel

PSMDTAG:CMDLET: Get-Alias, gal,

PSMDTAG:INTERNAL: built in aliases are READONLY, ALLSCOPE which makes reasonably safe to use in scripts.

0 comments

Discussion is closed.

Feedback usabilla icon