Browsing Posts in PowerShell

PowerShell Unix-style Recently I was on the PowerScripting Podcast hosted by Hal Rottenberg and Jonathan Walz. I had a great time talking about PowerShell from a developer’s perspective and psake, my PowerShell-based build system, in particular. You can find the interview on Episode 56 here. Thanks to Hal and Jonathan for having me on the show.

Now let’s talk PowerShell and scripting for developers. I don’t see a lot of developers using the command line and this surprises me. Maybe it’s my Unix background that attracts me to the command line. Maybe it’s my belief that sustainable, maintainable development is facilitated by a CI process, which necessitates being familiar with the command line. Maybe it’s because the only way to create reproducible results is to automate and the easiest way to automate is the command line. Whatever the reason, I believe that developers should become familiar with copying, building, deploying, and otherwise automating tasks via the command line.

So why PowerShell? PowerShell is a full-fledged programming language focused on object-based shell scripting. Note that I didn’t say “object-oriented”. You cannot create class hierarchies or define polymorphic relationships, but you can instantiate and use objects defined in other .NET-based programming languages (or COM objects). PowerShell is a shell language, meaning that it serves the same role as cmd.exe, bash, tcsh, etc. It’s raison d’etre is automating the command prompt. Manipulating directories/files, launching applications, and managing processes is really straightforward.

Microsoft is investing heavily in PowerShell and providing support for managing Windows Server 2008, IIS7, SQL Server 2008, Exchange 2007, and other Microsoft server products. This means that we are approaching the Nirvana that is end-to-end build to deploy. Imagine getting latest from your source repository, building the code, unit/integration testing the code, building the documentation, labelling the build, and deploying into a QA environment! The entire process is automated and reproducible. You know the exact version of the code that went into QA. When you get the green light to do a live deployment, you give the same PowerShell scripts to the IT deployment team who uses it to deploy the compiled (and QA’d) bits into the production environment! Who best to write these deployment scripts than your friendly neighbourhood IT Pro, who is intimately familiar with the production and QA environments. This is a great collaboration point to get the IT Pros, who will be deploying and maintaining your apps, involved in the development process.

Enough chitchat. Show me the code! Believe it or not, you probably already know a fair amount of PowerShell. Many of the commands you’re familiar with in cmd.exe work in PowerShell. (More surprisingly, many of the common commands you know from bash, tcsh, or other Unix shells also work!) The command line arguments are often different, but the basic familiar commands are there. So try out dir, cd, copy, del, move, pushd, popd, … (If you’re a old Unix hacker, you can try out ls, man, kill, pwd, ps, lp, cp, … Unfortunately there is no grep equivalent built in, which is terribly unfortunate.) All of these commands are actually aliases to PowerShell commands, which are named by VERB-NOUN, where NOUN is singular. For example to get a list of running processes, you run Get-Process, which is aliased to “ps”.

PowerShell is very conducive to experimentation. You can always find out more about a command or alias typing “Get-Help [CmdName|Alias]” or simply “help [CmdName|Alias]” since help is an alias for Get-Help. (N.B. PowerShell is case insensitive.) You can also look for commands by typing part of the command and pressing tab repeatedly. For example, if you want to find all set- commands, type “set-[TAB][TAB]…” to display Set-Acl, Set-Alias, etc. You can also look for commands using wildcards. Type “*-Acl[TAB][TAB]…” displays Get-Acl and Set-Acl.

So start playing around with PowerShell. Learn what it can do for you. Next time, we’ll look at writing re-usable scripts for accomplishing common developer tasks. Until then, happy scripting!

psake 

A build automation tool… now with less XML…

psake is a build automation tool written in PowerShell. It avoids the angle-bracket tax associated with executable XML by leveraging the PowerShell syntax in your build scripts. psake has a syntax inspired by rake (aka make in Ruby) and bake (aka make in Boo), but is easier to script because it leverages your existent command-line knowledge.

psake is pronounced sake – as in Japanese rice wine. It does NOT rhyme with make, bake, or rake.

psake is a proof-of-concept still in the early stages of development. It consists of a single file, psake.ps1, which contains all the logic for creating a graph of dependent tasks and executing them in the correct order. You can download it from Google Code using Subversion or TortoiseSVN:

svn checkout http://psake.googlecode.com/svn/trunk/ psake-read-only

Here is a simple psake build script:

properties {
  $testMessage = ‘Executed Test!’
  $compileMessage = ‘Executed Compile!’
  $cleanMessage = ‘Executed Clean!’
}

task default -depends Test

task Test -depends Compile, Clean {
  Write-Host $testMessage
}

task Compile -depends Clean {
  Write-Host $compileMessage
}

task Clean {
  Write-Host $cleanMessage
}

The properties and task script blocks can contain any valid PowerShell commands. To execute the script, simply type:

psake [task(s)]

(This assumes that psake.ps1 is in your PowerShell path.) If you don't specify a task or list of tasks (separated by spaces), it will look for a task named "default". You can display the command line syntax by typing:

psake -help

psake [buildFile] [tasks] [-framework ver] [-debug]
  where buildFile is the name of the build file, (default: default.ps1)
        tasks is a list of tasks to execute from the build file,
        ver is the .NET Framework version to target - 1.0, 1.1, 2.0, 3.0, or 3.5
            3.5 is the default
        debug dumps information the tasks.
psake -help
  Displays this message.

Remember that psake is syntactic sugar around PowerShell. So anything you can do in PowerShell, you can do in psake. That means that you can run MSBuild, NAnt, or other scripts. There is no need to completely replace your current build system. You can use psake to automate and extend it!

psake automatically adds the appropriate version of .NET Framework to its path. So you can access MSBuild, csc.exe, vbc.exe, or any other tools installed in $env:windir\Microsoft.NET\Framework\$version\ without the fully qualified path.

task default -depends DisplayNotice
task DisplayNotice {
  msbuild /version
}

As I mentioned earlier, psake is a proof-of-concept. You're likely to find some rough edges. I am releasing to the community under a MIT License. I would love to get your feedback and ideas for improving it. If you are interested in contributing, please contact me. Go forth and free yourselves from the shackles of executable XML! Take a sip of psake and enjoy!