PowerShell: Using PowerShell to Debug .NET Class Libraries

PowerShell is so wicked cool. I love it more and more each day I use it. Latest trick is using it to debug or my class libraries without having to have a supporting unit test or console project.

Though this method of testing / debuging process isn't as good as unit testing, it sure is handy for some small client utilities or where you just want to "try" something in one of your class libraries without changing all your unit tests.

What you need to do is set your project to launch an external command and point it to your PowerShell installation, typically: C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe

The command line arguments for your debug external program should be: -NoExit -command "& { . .\Debug.ps1 }"

Then, add a file to your project called Debug.ps1, make sure you set it to copy to the output directory.

When you run your class library in debug mode it will launch the PowerShell console and then execute the Debug.ps1 file. My file contains something like the following to load my assembly and a few functions to automate some of the things I might do while debugging. After this script runs, you will be left with a fully functioning PowerShell instance that you can use to further test your class library.

Did I mention this is an awesome trick for building custom PowerShell commands? Well, I'm pretty sure it is, but I have not gotten that far, yet.

#Debug.ps1
[System.AppDomain]::CurrentDomain.AppendPrivatePath($PWD)
[System.Reflection.Assembly]::LoadFrom("DotDeploy.dll")

function global:New-DeploymentDefinition
{
    return New-Object DotDeploy.DeploymentDefinition
}

function global:New-DeploymentCopyFileTask
{
    param ( [string]$sourcePath, [string]$destinationPath )
    return New-Object DotDeploy.DeploymentCopyFileTask $source,$destination
}

function global:New-DeploymentServer
{
    param ([string]$server, [int]$port)
    return New-Object DotDeployt.DeploymentServer $server,$port
}

$source = New-DeploymentServer "MARIO",9216
$destination = New-DeploymentServer "LUIGI",9216
$deployment = New-DeploymentDefinition
$task = New-DeploymentCopyFileTask "C:\Program Files\DotDeploy\v1.0\Configuration" "C:\Program Files\DotDeploy\v1.0\Configuration"
$task.Recursive = $true
$task.InputFilter = "*.xml"
$deployment.Tasks.Add($task)
$deployment.Source = $source
$deployment.Destination = $destination
$destination.Lock()
$deployment.Deploy()
$destination.Unlock()

Update Note: Make sure when you load your assembly you use LoadFrom and not LoadFile becasue LoadFile will not resolve dependencies but LoadFrom does. You can also append a private path to the current AppDomain as shown (added) in the example.

No Comments