# Tuesday, July 01, 2008

Why do such a thing? Well, if you’ve created your own aliases for commands and you try to give someone your ps1 script file, it will not run because they have not got the same aliases defined as you. Also, scripts that use fully-resolved names like “Get-ChildItem” are more readable for a newcomer to PowerShell than one that is using the unix-like “ls" alias for example. "Get-ChildItem" leads quite directly to the MSDN documentation, but "ls" might lead you anywhere. Before you publish a script online somewhere for the world to use, it’s important that you try to remove any aliases and replace them with the native command names.

Doing this kind of thing has been talked about before but it was always a very difficult thing to do with PowerShell v1.0, what with the lack of BNF documentation describing the grammar etc. Thankfully, it's a lot easier to do with PowerShell v2.0 (currently at release CTP2) because the team has exposed the Tokenizer for use in scripts. There's been suprisingly little use of it so far, so I figured I'd start the ball rolling with a series of articles based around it. So, let's look at an example script that uses aliases and put it through the meat grinder:

image

As you can see, it spits out the expanded script to the output stream. The informational messages are written to the host, so they won't interfere if you redirect the output to a file like: .\resolve-aliases.ps1 in.ps1 > out.ps1

Here's the Resolve-Aliases.ps1 script itself:

  1. #requires -version 2  
  2. param($filename = $(throw "need filename!"))  
  3.  
  4. $lines = $null 
  5. $path = Resolve-Path $filename -ErrorAction 0  
  6.  
  7. if ($path) {  
  8.     $lines = Get-Content $path.path  
  9. } else {  
  10.     Write-Warning "Could not find $filename" 
  11.     exit  
  12. }  
  13.  
  14. # Initialize  
  15. $parser = [system.management.automation.psparser]  
  16. $errors = new-object system.management.automation.psparseerror[] 0  
  17.  
  18. do {  
  19.     $tokens = $parser::tokenize($lines, [ref]$errors)     
  20.     $retokenize = $false 
  21.       
  22.     if ($errors.count -gt 0) {  
  23.         Write-Warning "$($errors.count) error(s) found in script." 
  24.         $errors 
  25.         exit  
  26.     }  
  27.  
  28.     # look through tokens for commands  
  29.     $tokens | % {  
  30.         if ($_.Type -eq "Command") {  
  31.             $name = $_.Content  
  32.               
  33.             # is it an alias?  
  34.             # we use -literal here so '?' isn't treated as wildcard  
  35.             if ((!($name -eq ".")) -and (Test-Path -LiteralPath alias:$name)) {  
  36.                   
  37.                 # gcm may return more than one match, so specify "alias"  
  38.                 # filtering against name kludges the '?' alias/wildcard   
  39.                 $command = gcm -CommandType alias $name | ? { $_.name -eq $name }  
  40.                               
  41.                 # resolve alias which may lead to another alias  
  42.                 # so loop until we reach a non-alias  
  43.                 do {  
  44.                     $command = Get-Command $command.definition  
  45.                 } while ($command.CommandType -eq "Alias")  
  46.                   
  47.                 Write-Host -NoNewline "Resolved " 
  48.                 Write-Host -NoNewline -ForegroundColor yellow $name 
  49.                 write-host -nonewline " to "   
  50.                 write-host -ForegroundColor green $command.name           
  51.                   
  52.                 # Use a stringbuilder to replace the alias in the line  
  53.                 # pointed to in the Token object. StringBuilder has a much  
  54.                 # more precise Replace method than String. This allows us to  
  55.                 # replace the token with 100% confidence.  
  56.                 $sb = New-Object text.stringbuilder $lines[$_.startline - 1]  
  57.                 $sb = $sb.replace($name, $command.Name, $_.startcolumn - 1, $_.length)  
  58.                 $lines[$_.startline - 1] = $sb.tostring()  
  59.                   
  60.                 # now that we've replaced a token, the script needs to be reparsed  
  61.                 # as offsets have changed on this line.   
  62.                 $retokenize = $true 
  63.                   
  64.                 # break out of pipeline, (not 'do' loop)  
  65.                 continue;  
  66.             }  
  67.         }  
  68.     }  
  69. } while ($retokenize)  
  70.  
  71. Write-Host "" # blank line  
  72.  
  73. # output our modified script  
  74. $lines 

Of course, this requires PowerShell v2.0 CTP2. Next in the series, I'll give you a script to check your ps1 scripts for backwards compatibility against PowerShell 1.0. That should be handy for those naughty admins out there who despite all the warnings have installed v2 in production. ;-)

posted on Tuesday, July 01, 2008 6:43:07 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [2] Trackback
Related posts:
PowerShell Script Provider
PowerShell ISE Hacking: Change default save encoding to ASCII
PowerShell 2.0 – PSCX Labs: Invoke-Reflector
PowerShell 2.0 – Developer Essentials #1 – Initializing a Runspace with a Module
SharePoint Resources & Localization – What, Where and Why?
PowerShell 2.0 – Partial Application of Functions and Cmdlets

Referred by:
resolve all (www.google.com) [Referral]
aliases (search.live.com) [Referral]
http://images.google.com/imgres?imgurl=http://www.nivot.org/... [Referral]
examples how to resolve loops through alias (www.google.co.in) [Referral]
resolve aliases (www.google.com) [Referral]
how to fetch more than 1 alias name (www.google.com) [Referral]
http://images.google.no/imgres?imgurl=http://www.nivot.org/c... [Referral]
http://images.google.com/imgres?imgurl=http://www.nivot.org/... [Referral]
alias of www.google.com (www.google.com) [Referral]
.blogspot.com referral script (www.google.co.uk) [Referral]
powershell psparser tokenize (www.google.com) [Referral]
Powershell alias to full name script (www.google.com) [Referral]
[System.Management.Automation.PsParser]::Tokenize (www.google.fr) [Referral]
unix resolve alias (www.google.com) [Referral]
all alias to script (www.google.es) [Referral]
PSparser (www.google.com) [Referral]
resolve alias unix (www.google.co.uk) [Referral]
powershell parse alias (www.google.com) [Referral]
MSCS cluster alias won't resolve (www.google.com.au) [Referral]
sharepoint site is resolving old name for alias (www.google.com.sg) [Referral]
powershell psparser (www.google.com) [Referral]
alias list all alias (www.google.com) [Referral]
psparser (www.google.com) [Referral]
PSParser (www.google.com) [Referral]
how to find all alias used in unix (www.google.com) [Referral]
PSParser powershell (www.kumo.com) [Referral]
sharepoint stringbuilder resolve [% (www.google.com) [Referral]
powershell v2 streams error redirect to host (www.kumo.com) [Referral]
tokenize string powershell psparser example (www.google.com) [Referral]
powershell error redirect (www.bing.com) [Referral]
PSParser.Tokenize (www.google.co.uk) [Referral]
resolve all errors (www.google.ae) [Referral]
psparser (www.google.com) [Referral]
powershell parse unix aliases file (www.google.com) [Referral]
powershell psparser (www.bing.com) [Referral]
aliases (www.bing.com) [Referral]
powershell tokenize (www.google.com) [Referral]
unix resolve and alias (www.bing.com) [Referral]
Unix resolve alias server name (www.google.co.uk) [Referral]
how i find all aliases for a host (www.google.ro) [Referral]
alias file parser (www.google.com) [Referral]
unix use alias in script (www.google.com) [Referral]
www.nivot.org PSParserTricks1NdashResolveAllAliasesToDefinitionsInAScript (www.google.com) [Referral]
while resolving the alias for object 1 defined on lines (www.google.com) [Referral]
how to get all alias to host (www.google.com) [Referral]
unix aliases parse (www.google.gr) [Referral]
http://www.lycos.fr/?query=get+host+aliases&page2=2&tab=web&... [Referral]
oascript resolve alias (www.google.com) [Referral]
stringbuilder Remove blank lines (www.bing.com) [Referral]
system.management.automation.psparser (www.google.com) [Referral]
unix alias wildcard !* (www.google.com) [Referral]
www.google.com won't resolve (search.yahoo.com) [Referral]
psparser tokenize (www.google.co.uk) [Referral]
powershell tokenize string return token (www.google.nl) [Referral]
google won't resolve (www.altavista.com) [Referral]
PowerShell V2 MSCS (www.google.com) [Referral]
find all host aliases (www.bing.com) [Referral]
resolve path from alias (www.google.com) [Referral]
powershell alias google (www.google.com) [Referral]
referral google.com/imgres (www.google.com) [Referral]
"find all host aliases" (www.altavista.com) [Referral]
psparser (www.bing.com) [Referral]
psparser (www.google.com) [Referral]
psparser examples (www.google.co.uk) [Referral]
psparser (www.bing.com) [Referral]
psparser (www.bing.com) [Referral]
unix resolve.com (search.yahoo.com) [Referral]
powershell syntax tricks (www.google.co.uk) [Referral]
how to resolve alias unix command (www.google.fr) [Referral]
unix how to resolve an alias in a script (www.google.com) [Referral]
http://pipes.yahoo.com/pipes/pipe.info?_id=FDuugRdE3RGtLMQA2... [Referral]
SharePoint - string builder clipboard (www.google.com) [Referral]
powershell resolve-alias (www.google.com) [Referral]
resolve all aliases (www.google.ch) [Referral]
unix resolve alias (www.google.com) [Referral]
aliases www (www.google.pl) [Referral]
unix resolve host alias (www.google.co.uk) [Referral]
Windows Based Script Host (hk.image.search.yahoo.com) [Referral]
PowerShell PSparser (www.google.co.jp) [Referral]
psparser nivot (www.google.co.jp) [Referral]
unix alias & how to know all alias of the host (www.google.ca) [Referral]
windows based script host (images.search.yahoo.com) [Referral]
http://tw.babelfish.yahoo.com/translate_url_load?lp=en_zt&tr... [Referral]
powershell PSParser (www.bing.com) [Referral]
psparser]::tokenize (www.google.es) [Referral]
PSParser (www.google.ru) [Referral]
PSParser (www.google.ru) [Referral]
http://yandex.ru/yandsearch?text=psparser.tokenize&lr=65 [Referral]
http://www.google.com/imgres?imgurl=http://www.nivot.org/con... [Referral]
powershell psparser tokenize (www.bing.com) [Referral]
PS1 tokenize string (www.bing.com) [Referral]
Tuesday, July 01, 2008 6:53:13 PM (Eastern Daylight Time, UTC-04:00)
viva le naughty admins
Wednesday, July 02, 2008 2:40:54 AM (Eastern Daylight Time, UTC-04:00)
For another example of how the tokenizer can be useful, I wrote a script that highlights PowerShell syntax for HTML here:

http://out-web.blogspot.com/2007/11/powershell-syntax-highlighting-for-html.html
Comments are closed.