Channels ▼
RSS

Mobile

PowerShell for Developers with Admin Tasks


Path

There are several locations I add to the path. For these locations, I define short names because they'll be used through the PATH and not directly in the command-line, so I don't need significant names.

$pd = 'C:\Python27\' # Python dir
$py3d = 'C:\Python32\' # Python dir
$ps = $pd + 'Scripts' # Python scripts
$ipd = $program_files + 'IronPython 2.7.1\' # IronPython dir
$ptd = 'C:\PuTTY\'
$td = 'C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE'
$components = $ipd, $pd, $ps, $ptd, $td, $env:PATH
$env:PATH = [string]::join(';', $components)

Aliases/Functions

I accumulated several useful functions I use frequently (which are sometimes used by other functions in the profile). I use descriptive names for the functions, and if I plan to use them interactively, I also define short aliases. For example, the ElevateProcess() function enables me to run a program with Administrator privileges. I added the alias sudo for quick interactive use:

function ElevateProcess
{
    $file, [string]$arguments = $args;
    $psi = new-object System.Diagnostics.ProcessStartInfo $file;
    $psi.Arguments = $arguments;
    $psi.Verb = "runas";
    $psi.WorkingDirectory = get-location;
    [System.Diagnostics.Process]::Start($psi);
}

set-alias sudo ElevateProcess

Another example is a little function to find all the aliases to a command. It is very simple and just uses an existing Cmdlet with a switch, but it's easier for me to remember via an alias to it:

function GetAliasNames([string]$command)
{
  Get-Alias -Definition $command
}

set-alias gan GetAliasNames

I also use lots of small functions that really work as aliases with arguments. For example, I often want to kill all the instances of a certain process by name. This can be done pretty easily in PowerShell with: Stop-Process -ProcessName <process name>. You can use the kill alias instead of Stop-Process, but it's still too verbose for me. So I defined a couple of functions to kill Erlang (when working with local RabbitMQ server) and Visual Studio (very useful when installing plugins or when it hangs):

function kvs { Stop-Process -ProcessName devenv }
function kerl { Stop-Process -ProcessName erl }

Quick Command Launchers

Another time-saver is quick program launchers. I use short functions to launch various programs (sometimes with arguments). Here are some examples:

function ipy 
{
    $iron_python = $ipd + 'ipy64.exe' 
    & $iron_python $args[0] $args[1] $args[2] 
}

function py3 
{
    $python3 = $py3d + 'python.exe' 
    & $python3 $args[0] $args[1] $args[2] 
}

function mongo
{
    & "C:\Users\Gigi\Downloads\mongodb-win32-2.0.4\bin\mongo.exe" 
    $args[0] $args[1] $args[2] $args[3] $args[4]
}

Prompt

The prompt is important in interactive use. You can put pretty much anything you want there. I like to know where I am, so the current directory is a no-brainer. I don't care much about the host because this information can be displayed in the console window title (it doesn't change from one command to the next normally). I also like to know the time a command completed because I often run several lengthy commands in multiple console windows over and over (for example, for deployment after a code change) and I want to be sure of the last time I ran a particular command. There is nothing remarkable about these requirements. The only twist I added to my prompt is that I don't want to display the full path. As a developer, I often work with multiple workspaces with deep directory structures. If I display the full path, it takes a significant part of the line and doesn't leave enough space to type the command itself.

Displaying just the last part of the path doesn't work for me either because I often work on multiple copies of the same project from different branches in parallel. The solution I came up with is to compress most of the long prefix of common trees into a unique mnemonic abbreviation. For example, when I work in the Testing tree, I collapse the path C:\root\ProjectCool\Testing to [X]. A path like C:\root\ProjectCool\Testing\Tools shows up as [X]\Tools and is very easy to distinguish from the same project in the ProjectCool_featureX branch, whose path is C:\root\ProjectCool_FeatureX\Testing\Tools but shows up as [x2]\Testing\Tools\.

The trick is to always have good abbreviations for the trees and branches I currently work on. To set the prompt, you need to have a Prompt() function in your profile that returns a string. In the code below, I keep a hash of path prefixes to abbreviations and I check whether the current working directory matches any of the prefixes — and add the current time, too.

function Prompt
{ 
    $hash = @{
      "c:\users\gigi" = "~"; }
     “c:\root\ProjectCool” = “[X]”;
     “c:\root\ProjectCool_FeatureX” = “[X2]”;


    $result = $PWD.Path
    $fullPath = $PWD.Path.ToLower()
    foreach ($name in $hash.Keys)
    {
        if ($fullPath.StartsWith($name))
        {            
            $path = $PWD.Path.Substring($name.Length);
            if ($path[0] -eq "\")
            {
                $path = $path.Substring(1)
            }
            $result = $hash[$name] + " " + $path;
        }
    }
    (get-date -f HH:MM:ss) + " " + $result + "> "
}
}

Text Searching (grepping)

PowerShell is all about objects, but it doesn't neglect text processing. The equivalent of the UNIX/Linux workhorse grep is Select-String. For some reason, the PowerShell designers didn't alias it to grep, so it is not as discoverable. I defined my own alias to it: set-alias grep Select-String.

When working with objects, the PowerShell equivalent to Select-String/grep is Select-Object. This is normally more powerful and robust. I defined a couple of functions that help me grep over a bunch of objects by converting each object to its text representation, then using Select-String on the result. I aliased this concoction as sgrep:

# Convert a collection object to a collection of their textual representation
function Objects2Strings
{
    $input | ForEach-Object $_ { $_.ToString() }
}

# Convert input to strings (good for searching in filenames without digging into file contents)
function GrepFromPipe
{
    $input | Objects2Strings | select-string -Pattern $args[0] 
}

set-alias sgrep GrepFromPipe

Conclusion

PowerShell was designed with the administrator in mind, but it can be amazingly useful in the hands of developers, too. If you find yourself frequently performing tedious and error-prone tasks, consider using PowerShell to make your life easier. PowerShell is powerful, well-designed, and has a good ecosystem and community. It will also be around for a long time given its adoption, ongoing development, and integration with Microsoft products.


Gigi Sayfan specializes in cross-platform object-oriented programming in C/C++/ C#/Python/Java with emphasis on large-scale distributed systems, and is a long-time contributor to Dr. Dobb's.


Update: This article was updated (that is, shortened) on 28 May 2013 due to possible legal action from Roblox for mention of one of their tools in passing.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video