Recently I had modified the smmCampaignBroadcast class to call a custom class/method that I had used and modified, to send emails using CLR via the System.Net.Mail assembly (which was being used elsewhere... see my blog on Sending Emails From Dynamics AX Without Outlook). It worked great, until a certain a condition caused the Send() function to fail. The problem came in to play with despite the fact that I had try/catch blocks around core pieces code in the function (meant to alert the user of errors) in this particular scenario, the process was simply taking a dump, and the error causing the problem was not being caught. Upon stepping through the code with the debugger, immediately after hitting the problem line of code (which was the Send() function as mentioned above) the debugger stepped into a \Classes\Application\ttsNotifyAbort() method, which basically aborted the entire process, not allowing my try/catch block around the Send() call to acknowledge the error.
Upon some research, it appears that the problem is related to levels of ttsbegin/ttscommit blocks, and apparently if a CLR error occurs inside of a ttsbegin/ttscommit block, you cannot trap the error until you are outside the block (and in the case of nested ttsbegin/ttscommit blocks, you must be outside of the highest level).
Using the Stack Trace in the debugger, I analyzed the code, to identify where the first ttsbegin/ttscommit block was, and then wrapped that piece of code with a try/catch block meant to catch a CLR error. So, in the smmCampaignBroadcast::broadcast() method I made the following changes:
try
{
ttsbegin;
…….
ttscommit;
}
catch(Exception::CLRError)
{
info(CLRInterop::getLastException().ToString());
}
Finally, I was able to see what was going wrong!