[Windbg Script] Retrieving queries/stored procedures from .NET application

Ok, you are debugging a .NET application. You need to find out the queries and stored procedures being executed from the threads accessing the database, but you don’t know how. . . Good news! It’s not a problem anymore!

This script shows you all the queries or stored procedures associated with a SQLCommand or OracleCommand object. Moreover, you can click on it to get more details and the threads which use it.

If you compare this script with the last one, from my previous post, you’ll understand why I prefer the DML approach and why you need more work than the previous approach.

These are the screenshots:

 

 

Source code for GET_SQLCOMMAND.TXT:

$

$$

$$ =============================================================================

$$ It shows the SQL commands from a .NET application. It gives you detailed information

$$ and the threads using the query/stored procedure you selected.

$$ Useful for Oracle and SQL Server.

$$

$$ Compatibility: Win32.

$$

$$ Usage: Use $$>< to run the program.

$$

$$ Requirements: Public symbols.

$$

$$ If necessary change the filename below to include your path and filename.

$$ By default it uses the WinDbg path and the default file name is GET_SQLCOMMAND.TXT

$$

$$ Roberto Alexis Farah

$$ Blog: https://blogs.msdn.com/debuggingtoolbox/

$$

$$ All my scripts are provided "AS IS" with no warranties, and confer no rights.

$$ =============================================================================

$$

ad /q *

r @$t0 = 0

r @$t1 = 0

.printf /D "<b>\nClick on the queries/stored procedures below to get more details and to find out the threads using it.\n\n</b>"

.block

{

    .block

    {

        as ${/v:ScriptName} MYSCRIPTS\\GET_SQLCOMMAND.TXT

    }

    .block

    {

        as SQLCommand .block

        {

            !DumpObj poi(@$t0+0x10)

            !DumpObj @$t0

            !GCRoot @$t0

        }

    }

    .block

    {

        as OracleCommand .block

        {

            !DumpObj poi(@$t0+0x14)

            !DumpObj @$t0

            !GCRoot @$t0

        }

    }

}

.foreach(obj {!dumpheap -short -type System.Data.SqlClient.SqlCommand } )

{

    r @$t1 = 1

    .printf /D "<link cmd=\"r @$t0 = ${obj}; ${SQLCommand} ;ad ${/v:ScriptName}; $$><${ScriptName}\"><b>%mu</b></link>\n\n", poi(${obj}+0x10)+0xc

}

.foreach(obj {!dumpheap -short -type System.Data.OracleClient.OracleCommand } )

{

    r @$t1 = 1

    .printf /D "<link cmd=\"r @$t0 = ${obj}; ${OracleCommand} ;ad ${/v:ScriptName}; $$><${ScriptName}\"><b>%mu</b></link>\n\n", poi(${obj}+0x14)+0xc

}

.if(0 = @$t1)

{

    .printf /D "<b>\nNo SQL commands found.\n</b>"

}

Read me.