System.IO.File::OpenRead("c:\\nothing_here");
System.IO.FileNotFoundException: Could not find file 'c:\nothing_here'.This happens when there is an exception handler in the application that handles the error and merely puts a message to infolog. Or if it’s an X++ exception, because D365FO doesn’t show stack trace for them. You can’t use breakpoints because you don’t know where you should put them. Wouldn’t it be great if Visual Studio interrupted execution immediately when the exception is thrown, i.e. at the first chance exception? Fortunately there is a way! Go to Visual Studio and open Debug > Windows > Exception Settings. Expand Common Language Runtime Exceptions, find FileNotFoundException (you can use the search box on the top) and tick the checkbox.
When you run the code again (with debugging), Visual Studio breaks the program when the exception is thrown and shows the dialog which is normally used for unhandled exceptions:
The example above used a .NET exception, FileNotFoundException. But can we use something like that with native X++ exceptions? Yes, we can!
I’ll use the following piece of code for my example:
HrmCompCreateGrid::construct().run();
I can’t merely put try/catch to my code, because there is no unhandled exception. The exception is already handled in some code called from run().
But I can ask Visual Studio to break on first chance exceptions.
X++ doesn’t use objects for exceptions; throwing an error means throwing an enum value (throw Exception::Error). But D365FO uses CLR (“.NET runtime”) and must play but its rules, therefore every X++ exception is converted to an instance of an exception class under the hood. The class is Microsoft.Dynamics.Ax.Xpp.ErrorException.
If you open Debug > Windows > Exception Settings again, you’ll notice that Microsoft.Dynamics.Ax.Xpp.ErrorException isn’t in the list of Common Language Runtime Exceptions. But it doesn’t matter, because you can add it there.
Select Common Language Runtime Exceptions node and click the green plus button:
Type in Microsoft.Dynamics.Ax.Xpp.ErrorException
and press Enter. The exception is now in the list and Visual Studio will break every time when an X++ error exception is thrown.
When you run the demo code again (with debugging), Visual Studio will stop at the throw statement in createGrid() method.
Finding the place where an exception is thrown may be time consuming, especially if it’s handled somewhere but you don’t know where. This little trick may save you a huge amount of time.
It also shows that there is a lot to gain from the new platform and from Visual Studio, if you use them creatively.
Note that things like this are also applicable to AX 2012, if X++ code is executed as CIL (which, unlike in D365FO, happens only in some cases). I sometimes intentionally ran code in CIL just to get access to features that aren’t available in the X++ debugger.