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]:
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:
dnx PATH_TO_DNX\bin\lib\Microsoft.Dnx.Tooling\Microsoft.Dnx.Tooling.dll restore
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:
c:\code\helloWorld>rem @Echo OFF
c:\code\helloWorld>"C:\Users\pawel\.dnx\runtimes\dnx-clr-win-x188.8.131.52-beta8-15625\bin\dnx" "C:\Users\pawel\.dnx\runtimes\dnx-clr-win-x184.108.40.206-beta8-15625\bin\lib\Microsoft.Dnx.Tooling\Microsoft.Dnx.Tooling.dll" restore
Microsoft .NET Development Utility CLR-x86-1.0.0-beta8-15625
Restoring packages for c:\code\helloWorld\project.json
Writing lock file c:\code\helloWorld\project.lock.json
Restore complete, 823ms elapsed
NuGet Config files used:
c:\code\helloWorld>exit /b 0
Actual line that runs DNX is:
"%~dp0dnx" %DNX_OPTIONS% "%~dp0lib\Microsoft.Dnx.Tooling\Microsoft.Dnx.Tooling.dll" %*
%~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:
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 !
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.
c:\code\helloWorld>dnu --debug list
Process Id: 31992
Waiting for Debugger to attach...
And that’s it! Play around with code and give me a shout is anything is unclear.