Scripting WinDbg with PowerShell

A while back, Roberto Farah published a script library to help control WinDbg through PowerShell. I’ve been using WinDbg for more debugging lately, and decided (after following one to many object references by hand) that I needed to script my investigations.

PowerDbg is definitely helpful – Roberto has tons of great scripts published that help analyze all kinds of interesting data. It also made me think of an alternative approach that works around some of the problem areas – PowerDbg uses SendKeys, window focusing, and used WinDbg logging as the communication mechanism. After some investigation, I thought that automation of the command-line version (cdb.exe) through its input and output streams might be easier and more efficient – which indeed it was.

You set up a remote from the Windbg instance you want to control, and then the WinDbg module (below) connects to the remote session (by manipulating standard in / standard out of cdb.exe) to manage its output.

I’ve shared this module now in the PowerShell Gallery. To run it, just run:

Install-Module WinDbg –Scope CurrentUser

Let’s see how it works!

Here’s an example program that we want to debug:

image

First, import our module, launch the program, and then connect. If you’ve got the module, you can follow along at home 🙂

Import-Module WinDbg

Set-Location (Get-Module WinDbg).ModuleBase

cd tests

$app = Start-Process .\TestApplication.exe -PassThru -WindowStyle Hidden

New-DbgSession -Id $app.Id

Now, we can use Invoke-DbgCommand to do all of our usual debugging things, like enumerating threads, switching them, etc. Invoke-DbgCommand has an alias, dbg.

Invoke-DbgCommand !threads

Invoke-DbgCommand ~5s

dbg !ClrStack

dbg k

Now that you have these in PowerShell, you can do any kind of text-based manipulation you’d like.

image

What does the debugger know about our TestClass?

dbg !dumpheap -type TestClass

Turns out, it knows some cool stuff. Again, you can do some more amazing text parsing and automation:

image

One thing that the WinDbg module includes is a few basic scripts that automate some of this parsing for you. For example, Search-DbgHeap and Get-DbgObject. Explore, and have fun!

image

Also, if this project interests you, should definitely check out DbgShell. This is the hobby-time project of @JazzDelightsMe, and exposes much of the debugging engine into PowerShell as PowerShell objects. Incredible! I can’t wait to see that module continue to grow.

(Edit: 05/13/09 - Updated to support local kernel debugging)
(Edit: 01/11/19 – Improved over the last 10 years. Published to PowerShell Gallery, and completely rewrote post)

9 Responses to “Scripting WinDbg with PowerShell”

  1. Roberto Farah writes:

    Your solution is awesome! It’s going to be incorporated into PowerDbg as soon as possible! 🙂

  2. Andy Schneider writes:

    Lee, what are you using for formatting your code on your blog? I really like the color coding.

    Thanks,

    Andy

  3. Lee Holmes writes:

    Andy: It’s a highly customized version of http://blogs.msdn.com/powershell/archive/2009/01/13/how-to-copy-colorized-script-from-powershell-ise.aspx — I’ll be posting and update to the blog soon.

  4. feroze writes:

    hi! Andy: Your code does not seem to work with Powershell v2/CTP3 that I just downloaded from MSDN.

    Will you be fixing this example for that version?

  5. feroze writes:

    OOps, I should have said "lee", not "Andy". Sorry.

  6. Lavanya writes:

    Hi,

    I did the windbg server setup and then try to import windbg and connect to it.
    But I get this error,

    PS C:\Users\Administrator> import-module windbg
    WARNING: Some imported command names include unapproved verbs which might make them less discoverable. Use the Verb
    parameter for more detail or type Get-Verb to see the list of approved verbs.
    WARNING: Some imported command names contain one or more of the following restricted characters: # , ( ) {{ }} [ ] &
    / \ $ ^ ; : ” ‘ | ? @ ` * % + = ~
    PS C:\Users\Administrator> connect-windbg “tcp:port=10456,server=ingbtcpic5nb0bb”
    Exception calling “Start” with “1” argument(s): “The system cannot find the file specified”
    At C:\Windows\system32\WindowsPowerShell\v1.0\Modules\windbg\windbg.psm1:124 char:48
    + [System.Diagnostics.Process]::Start <<< connect-windbg “tcp:port=10456,server=ingbtcpic5nb0bb”
    PS C:\Users\Administrator> connect-windbg “tcp:port=10456,server=ingbtcpic5nb0bb”
    PS C:\Users\Administrator> Invoke-Windbgcommand .symfix
    Not connected. Use Connect-Windbg to connect to an instance of WinDbg.
    At C:\Windows\system32\WindowsPowerShell\v1.0\Modules\windbg\windbg.psm1:170 char:14
    + throw <<< Invoke-Windbgcommand k
    Not connected. Use Connect-Windbg to connect to an instance of WinDbg.
    At C:\Windows\system32\WindowsPowerShell\v1.0\Modules\windbg\windbg.psm1:170 char:14
    + throw <<<< "Not connected. Use Connect-Windbg to connect to an " +
    + CategoryInfo : OperationStopped: (Not connected. …ance of WinDbg.:String) [], RuntimeException
    + FullyQualifiedErrorId : Not connected. Use Connect-Windbg to connect to an instance of WinDbg.

    Please help me!!! I am a beginner

  7. F. Morrison writes:

    To prevent “Warning: Some imported command names contain…” you must:
    Change all functions with “-” (hyphen character) in the middle of the name to a name WITHOUT THE HYPHEN character.
    For example this is bad: function Resolve-Member
    This is good: function ResolveMember
    It’s going to be A LOT OF WORK to make these changes, so good luck and remember the lession learned:
    Thou Shalt Not Put Hypens In The Names Of PowerShell Functions Or Thou Shalt Burn In PowerShell Warning Hell 🙂

  8. Lee Holmes writes:

    Hey F. Morrison –

    That’s exactly the wrong advice 🙂 The error message that PowerShell gives is correct:

    PS C:\Users\leeholm> “function Un-ApprovedVerb { ‘Hi’ }” > c:\temp\Unapproved.psm1
    PS C:\Users\leeholm> Import-Module C:\temp\Unapproved.psm1
    WARNING: The names of some imported commands from the module ‘Unapproved’ include unapproved verbs that might make them
    less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose
    parameter. For a list of approved verbs, type Get-Verb.

    PS C:\Users\leeholm> Import-Module C:\temp\Unapproved.psm1 -Verbose
    (…)
    VERBOSE: The ‘Un-ApprovedVerb’ command in the Unapproved’ module was imported, but because its name does not include an
    approved verb, it might be difficult to find. For a list of approved verbs, type Get-Verb.
    (…)

    The answer is to name exported functions in a manner that is consistent with PowerShell’s approved verbs. Resolve-Member is not causing the problem.

    1 [C:\windows\system32]
    >> “function Resolve-Member { ‘Hi’ }” > c:\temp\Unapproved.psm1

    2 [C:\windows\system32]
    >> Import-Module C:\temp\Unapproved.psm1

    3 [C:\windows\system32]
    >>

  9. Evgeny Golov writes:

    Hello,

    Thank you for the great solution! It really helps a lot!

    Regarding “The system cannot find the file specified” upon running Connect-DbgSession -ArgumentList ‘-z c:\xfer\1.dmp’: I have cdb.exe only at these locations from the searched list:
    C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x64\cdb.exe
    C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe
    The Connect function didn’t work up until I copied the …\x64 folder contents into C:\Debuggers to match the “C:\Debuggers\cdb.exe” location for the cdb.exe.

Leave a Reply