Hacking DNX. Part two – debugging DNU utility

In part one I described how to prepare for debugging DNX. This part is focused on understanding and debugging DNU – the tool delivered with each DNX used to develop, build, pack and publish .NET projects.

This is part two of my series Hacking DNX.

Agenda [may change a bit]:

  1. Build & first debug session
  2. Debugging DNU Utility (this)
  3. Overview of DNX projects and architecture
  4. DNX internals

Understanding DNU

First and foremost to understand is that DNU utility is just a wrapper for running various commands from Microsoft.Dnx.Tooling.dll via DNX. For example:

translates to:

To understand more about running DNU utility I find it useful to edit dnu.cmd file and remove @Echo OFF line. File dnu.cmd can be found in the user profile folder (eg. c:\Users\user) and then .dnx\runtimes\RUNTIME_VERSION\bin\. Be sure to edit correct file from active runtime folder. Using .NET version manager list command (dnvm list) can help locate victim.

After editing dnu.cmd file helpful output can be seen in console. Example:

Actual line that runs DNX is:

where %~dp0dnx is replaced by drive and path to dnx, similarly ~dp0lib\Microsoft.Dnx.Tooling\Microsoft.Dnx.Tooling.dll to drive and path to Microsoft.Dnx.Tooling.dll. Last argument %* means all arguments passed to script.
Few things to note here:

  • via environment variable %DNX_OPTIONS% it is possible pass options to dnx
  • any parameters passed to script are going to be appended at the end of the dnx call

Basically what dnx.exe itself does is to bootstrap proper .NET version, load Microsoft.Dnx.Tooling.dll library, looks for it’s Main() method and run it. When looking into Microsoft.Dnx.Tooling source code specifically into Program class amazing fact arise – the Program class has constructor and Main method is a class method ! Moreover arguments are injected into constructor !

Debugging DNU

By setting %DNX_OPTIONS% environment variable arguments can be used to passed to DNX. Particularly the --debug option can be set to start debugging. But setting environment variable is a bit cumbersome to use in per execution scenario. But there is much simpler solution. The --debug flag and be applied directly to DNU and thus passed to Microsoft.Dnx.Tooling.dll to be processed.

Engineers from Microsoft again did a great job to ease debugging of Microsoft.Dnx.Tooling.dll.
Attach debugger
Above code is responsible for former output and behavior.

And that’s it! Play around with code and give me a shout is anything is unclear.

1 Comment

Leave a Reply