[PowerShell Script] PowerDbg v5.0—Using PowerShell to Control WinDbg


I’m very excited to present the new PowerDbg v5.0! There’s just one change, but it’s a HUGE change that makes PowerDbg extremely fast and easier to use.


 


Let me explain: Send-PowerDbgCommand is the heart of PowerDbg.


This is the cmdlet that sends information to WinDbg and retrieves information from WinDbg. However, this cmdlet is not efficient. It uses SendKeys to send commands. It works, but it’s very slow and you can’t change the windows focus when it’s running. In my opinion and in the opinion of others, including peers, this is the only flaw that PowerDbg has; however, it’s a big flaw.


 


When I created PowerDbg, my goal was to learn PowerShell while creating the tool. At that time I considered and discarded other approaches that would be more efficient than SendKeys. However, the best approach to solve the problem came recently from a PowerShell guru: Lee Holmes.


 


Lee Holmes’ approach is based on PowerShell v2.0. He created a very simple script used as a module that automates cdb.exe command-line debugger, which can communicate with any WinDbg instance configured as a server.


The commands are sent to WinDbg through a port that can be a TCP port.


After incorporating his approach into PowerDbg, we’ve created a much more powerful tool!


 


More great news: all PowerDbg scripts are fully compatible with PowerDbg 5.0! You don’t need to change anything! J


 


In this post I’m going to explain how to install, use PowerDbg, and describe all cmdlets and scripts done so far.


 


 


POWERDBG FILES


 


WinDbg.PSM1  ß Contains cmdlets used to communicate with WinDbg.


 


Microsoft.PowerShell_Profile.PS1 ß Contains cmdlets that parse command output. Uses WinDbg.PSM1 under the hood.


 


 


INSTALLATION


 


WinDbg.PSM1


 


Goes to %\Documents\WindowsPowerShell\Modules\WinDbg


 


 


Microsoft.PowerShell_Profile.PS1


 


Goes to %\Documents\windowspowershell


 


In order to know the exact location, use this command from PowerShell:


 


$profile


 


 


REQUIREMENT


 


PowerShell v2.0


 


 


USAGE


 


First, make sure you can run scripts:


 


set-executionpolicy remotesigned


 


From the WinDbg window type:


 


.server tcp:port=10456,server=ServerName   ß ServerName is your server name.


 


The command above enables a port communication with the WinDbg instance as the server. You can use other port numbers.


 


From the PowerShell window you must initialize the communication:


 


Import-module WinDbg  ß Importing our module WinDbg.PSM1


 


Connect-Windbg “tcp:Port=10456,Server=SERVER” ß Connects session to WinDbg instance.


 


Note: Don’t forget to load symbols and your extensions!


 


At this point you’re ready to use PowerDbg or PowerDbg scripts.


Example:


 


Analyze-PowerDbgThreads   ß Cmdlet.


 


.\PowerDbgScriptExceptions  ß Script.


 


Example 2:


 


Send-PowerDbgCommand “~* kpn 1000”


Parse-PowerDbgK


$ht = @{}


$ht = Convert-PowerDbgCSVToHashTable


 


Let’s display the stack for thread 0:


 


# Replace the internal frame delimiter by new line and displays the stack. 


write-host $ht[“0”].Replace($global:g_frameDelimiter, “`n”)


 


Example 3:


 


Send-PowerDbgCommand “!DumpObj  027a4c3c”


Parse-PowerDbgDUMPOBJ


$ht = Convert-PowerDbgCSVToHashTable


$ht[“Name:”]                 <– Displays the content of the field Name:


$ht[“MethodTable:”]    <– Displays the content of the field MethodTable: 


 


For more examples see the source code from PowerDbg scripts.


 


 


CMDLETS FROM POWERDBG


 


Send-PowerDbgCommand <command>


 


This was the most complex cmdlet, but now it’s just a wrapper for Invoke-WinDbgCommand.


SendPowerDbgCommand sends commands to WinDbg.


 


 


Parse-PowerDbgDT [$useFieldNames] 


Parses the output from the dt command and saves it into POWERDBG-PARSED.LOG using a CSV file format.


If $useFieldNames has a value, the cmdlet stores fields from struct/classes and values. Otherwise it stores offsets and values.


To convert the CSV file to a Hash Table use Convert-PowerDbgCSVToHashTable.


 


 


Convert-PowerDbgCSVToHashTable


 


Convert the output from the Parse-PowerDbg* cmdlets to a Hash Table.


 


 


Send-PowerDbgDML <$hyperLinkDML> <$commandDML>


 


Creates a DML command and sends it to WinDbg.


DML stands for Debug Markup Language. Using DML you can create hyperlinks that execute commands.


 


 


Parse-PowerDbgNAME2EE


 


Maps the output from the !name2ee and saves it into the CSV file POWERDBG-PARSED.LOG


Convert-PowerDbgCSVtoHashTable converts the output into a Hash Table.


 


 


Parse-PowerDbgDUMPMD


 


Maps the output from !dumpmd command and saves it into the CSV file POWERDBG-PARSED.LOG.


Convert-PowerDbgCSVToHashTable converts the output into a Hash Table.


 


 


Parse-PowerDbgDUMPMODULE


 


Maps the output from !DumpModule command and saves it into the CSV file POWERDBG-PARSED.LOG


Convert-PowerDbgCSVToHashTable converts the output into a Hash Table.


 


 


 


Parse-PowerDbgLMI


 


Maps the output from lmi command and saves it into the CSV file POWERDBG-PARSED.LOG


Convert-PowerDbgCSVToHashTable converts the output into a Hash Table.


 


 


Has-PowerDbgCOMMANDSUCCEEDED


 


Returns $true if the last command succeeded or $false if not.


 


 


Send-PowerDbgComment


 


Sends a comment, a string in bold, to the WinDbg window.


 


 


Parse-PowerDbgVERTARGET


 


Maps the output from vertarget command, either the Kernel Time or the User Time.


The output is saved into the CSV file POWERDBG-PARSED.LOG.


Convert-PowerDbgCSVToHashTable converts the output into a Hash Table.


 


 


Parse-PowerDbgRUNAWAY


 


Maps the output of !runaway 1 or !runaway 2 and stores the results into the CSV file POWERDBG-PARSED.LOG


Convert-PowerDbgCSVToHashTable converts the output into a Hash Table.


 


Attention! If you need to know the top threads consuming CPU time, use Convert-PowerDbgRUNAWAYtoArray. The items will be in the same exact order of the original command.


 


 


Convert-PowerDbgRUNAWAYtoArray


 


Returns an array of two dimensions corresponding to the output of !runaway 1 or !runaway 2.


 


 


Parse-PowerDbgK


 


Maps the output of k command and its variations like kv, kbn, kpn, etc.


The output is saved into the CSV file POWERDBG-PARSED.LOG


Convert-PowerDbgCSVToHashTable converts the output into a Hash Table.


 


Attention! This cmdlet doesn’t work with kPn. Another thing, it replaces “,” with $global:g_frameDelimiter to avoid conflict with the CSV delimiter.


 


 


Parse-PowerDbgSymbolsFromK


 


Maps just the symbols from k command and variations, saving the content into the CSV file POWERDBG-PARSED.LOG


Convert-PowerDbgCSVToHashTable converts the output into a Hash Table.


 


Attention! This cmdlet doesn’t work with kPn. Another thing, it replaces “,” with $global:g_frameDelimiter to avoid conflict with the CSV delimiter.


 


 


 


Parse-PowerDbgLM1M


 


Maps just the output from lm1m and stores it into the CSV file POWERDBG-PARSED.LOG


Convert-PowerDbgCSVToHashTable converts the output into a Hash Table.


 


 


Classify-PowerDbgThreads


 


Returns one array where the index is the thread number and the value is one of these values:


 


0 UNKNOWN_SYMBOL


1 WAITING_FOR_CRITICAL_SECTION


2 DOING_IO


3 WAITING


4 GC_THREAD


5 WAIT_UNTIL_GC_COMPLETE


6 SUSPEND_FOR_GC


7 WAIT_FOR_FINALIZE


8 TRYING_MANAGED_LOCK


9 DATA_FROM_WINSOCK


 


It’s very easy to add more symbols and constants to get a more granular analysis. Look at the source code for details.


             


 


 


Analyze-PowerDbgThreads


 


Analyzes and shows what each thread is doing and its corresponding CPU time, sorted by User Mode time.


This cmdlet is very useful for scenarios like hangs, high CPU, and crashes.


 


Attention! This command requires thread information if debugging a dump file.


 


 


 


Parse-PowerDbgPRINTEXCEPTION


 


Maps the output from  !PrintException command and saves it into the CSV file POWERDBG-PARSED.LOG.


The following fields are considered while others are ignored:


 


Exception object:


Exception type;


Message:


InnerException:


HRESULT:


 


Convert-PowerDbgCSVToHashTable converts the output into a Hash Table.


 


 


Parse-PowerDbgDD-L1


 


Maps the output from dd <address> L1 or dd poi(<address>) L1 and saves the results into the CSV file POWERDBG-PARSED.LOG.


Convert-PowerDbgCSVToHashTable converts the output into a Hash Table.


 


 


Parse-PowerDbgGCHANDLELEAKS


 


Maps the output from  !GCHandleLeaks command and saves it into the CSV file POWERDBG-PARSED.LOG.


Convert-PowerDbgCSVToHashTable converts the output into a Hash Table.


 


 


 


Parse-PowerDbgDUMPOBJ


 


Maps the output from !DumpObj command and saves it into the CSV file POWERDBG-PARSED.LOG.


The assembly path and file name are saved using the key name ‘Assembly:’.


If the object is invalid the ‘Name:’ field will have the string “Invalid Object.” You may want to check this string to make sure you’ve got valid data.


The keys are the fields or Method Table, and values are the corresponding value.


Convert-PowerDbgCSVToHashTable converts the output into a Hash Table.


 


Attention! This version maps the fields below “Fields:” using MethodTable as key and Value as value. The problem with this approach is that the same MethodTable may appear more than once. If it happens, the last or most recent MethodTable and value will be considered.


Based on users’ feedback this approach may be changed in the near future.


 


 


Send-PowerDbgCTRL-BREAK and Send-PowerDbgResumeExecution are deprecated so they shouldn’t be used. They may be removed in future versions.


 


POWERDBG SCRIPTS


 


PowerDbgScriptDumpDict.PS1


 


Extracts the key/value pair from a Dictionary.


 


 


PowerDbgScriptExceptions.PS1


 


Displays the call stacks that have inner or hidden exceptions.


 


 


PowerDbgScriptGCHandleLeaksChart.PS1


 


It displays statistics and a chart from the top 20 objects leaking.


 


 


PowerDbgScriptHighCPU.PS1


 


It displays all threads consuming high CPU using a specific time as a threshold.


 


 


PowerDbgScriptSaveModule.PS1


 


It saves all modules that have a specific method. You provide the method name, and it gives you the corresponding modules.


 


 


New scripts and cmdlets are coming! Keep an eye on this blog.


Let me know if you find bugs or if you have suggestions for improvements.


The next version will have cmdlets for Win64.


 


Download PowerDbg