Sunday, September 9, 2007

Converting PowerShell scripts

 

I released this scripts about a week ago, in respond to a discussion in the Windows PowerShell news group. The goal is to read a script content and replace all command-let names to there alias's and vice versa.

The two functions below takes a script file path as the argument and convert it respectively. 

The first function, "Convert-CmdletToAlias", is more *secure* to use as it search for all cmdlet names (which doesn't contain non special chars) and replaces each one it finds with the first corresponding alias (there can be more than one).

The second function, "Convert-AliasToCmdlet", is more *dangerous*. Richard Siddaway reported that there is one major draw back. If you used the "%" sign as an alias for the foreach-object cmdlet, things may go wrong and behave unexpectedly. The reason is that "%" is also the symbol for modulo.

Keith hill suggested to parse the script before the final conversion. Didn't find a way so far so any suggestions/modifications are welcomed.


#### EDIT (11/01/07)  #####
Check out Keith's post on parsing the script for errors prior to executing it
PowerShell QuickTip: Preparsing Scripts to Check for Syntax Errors
#########################


Anyway, the conversion is not written back to the script file and only displayed back to the console. If you decide to use the functions, make sure to create a backup copy of the original scripts and always test the final converted script before using it in production.

 

 

Usage:

Convert-CmdletToAlias <filepath.ps1>
Convert-AliasToCmdlet <filepath.ps1>

 

###############################

 

function Convert-CmdletToAlias{
    param([string]$filepath)
    if(!(test-path $filepath)){
        write-warning "Error: File doesnt exist";
        break;
    }
    $src = [System.IO.File]::ReadAllText($filepath);
    $cmdlets = get-command | where {$_.CommandType -eq "Cmdlet"} | select name
    $cmdlets | foreach {

        $cmd = $_.name;

        if($src -match "\b$cmd\b") {
            $alias = @(get-alias | where {$_.definition -eq $cmd});   
            $src=$src -replace($cmd,$alias[0]);
        }
    }
    $src;
}

 

#####################

 

function Convert-AliasToCmdlet{

    param([string]$filepath)
    if(!(test-path $filepath)) {
        write-warning "Error: File doesnt exist";
        break;
    }
    #cls
    $src = [System.IO.File]::ReadAllText($filepath);
    $aliases = get-alias | select Name,Definition

    $aliases | foreach {

        trap{write-host "ERROR cant process alias: <$alias> -f red -b black"; continue}
        $alias = @($_)[0];
        $regex=[regex]::escape($alias.name);
        # for some reason this is not working "\b" +$regex +"\b"
        if($src -match "\s" +$regex +"\s"){
            $src=$src -replace($regex,$alias.definition);
        }
    }
    $src;       
}

No comments: