Last week, I mentioned an issue with running code in Service Mode which was related to Visual Studio Tools code failing to run. I have also seen other issues where Dexterity code fails to run, both in my products and also with other developers that I am providing consulting services to.
If you ask Microsoft for help, they will probably tell you to test in Desktop mode by either creating a test window or by hi-jacking a button with a trigger script to call your service procedure. The big problem is when the code works perfectly every time in Desktop mode and fails every time in Service mode.
So why would code behave differently between Desktop mode and Service mode?
The answer is simple, the environments are different. If we just look at Dynamics.dic, the code that logs in and sets up the environments in the two modes is different and not all of the global variables in memory have been initialized to the correct values, not all of the forms are opened and field values on those forms initialized.
I covered this in my previous article:
Now, the issue gets more complex when you start adding in third party products. Remember that in Dexterity terms a third party product is any dictionary that is not Dynamics.dic which could be developed by Microsoft, an ISV (Independent Software Vendor), by a consulting partner or by a customer.
The issue I faced was when posting a particular transaction type, the distributions where failing to post to the General Ledger. In Desktop mode, everything worked perfectly, but in Service mode it failed to post to GL. Also testing had previously shown that this code does work in Service mode, so why was it failing now?
How do you debug something like this?
The usual approach would be to use the script debugger with breakpoints and script logging…. all of which is not available in Service mode. When I first tried to get GP Power Tools to capture logs in Service mode, I found that Microsoft had disabled the Script Logging functionality entirely in Service mode and that turning it on would not produce any logs.
That’s why I developed the Dynamics Trigger Logging feature in GP Power Tools. Dynamic Trigger Logging allows you to define any of the supported Dexterity trigger events dynamically in a text file and it will register triggers before and after the event and add entries into the GP Power Tools log files when the events fire. The text file used by this feature can be edited using the window within GP Power Tools, or manually if desired.
The best way to use this functionality is to initially use GP Power Tools in Desktop mode to start logging (Tools >> Start Manual Logging from menus on any window) just before calling your Service Procedure and stop logging (Tools >> Stop Logging from menus on any window) immediately afterwards. This provides us with a Dexterity Script Log of the working code.
Identify the primary scripts that make up the flow of the code, starting with the Service procedure itself. Try to find scripts that are only executed once (or a few times) that will help you understand where in the overall process you are.
To start with only work with scripts called by the Service procedure or maybe one level down from the Service procedure. Add these into the Dynamic Trigger Logging Setup window and then test the service procedure.
You will see two logs created by GP Power Tools.
The first will be in the form GPPTools___<Date>.log and will show the Trigger list file being imported and the triggers being registered. The last line will have a summary of how many lines were imported and how many triggers were registered or failed to register.
The second will be in the form GPPTools_<User>_<Company>_<Date>.log (where the user and company will be the GP User and Company used for the web service call) and will show which of the triggers fired. You should see Before and After triggers for each script. If there is no After trigger then you know that an exception occurred before the script could finish.
It is an iterative process to keep adding events into the trigger list until you can narrow down where the code is behaving differently or crashing. Use a binary search method by selecting an event about halfway in the section of code. That way you know if that point in the code was reach and whether your problem is before or after that point.
Once you found out what is happening and where in the code that is, you can start to identify the cause.
Back to my issue, I was able to confirm that the script to post distributions was not being called. After a bit more research to find out possible reasons why, I found that the calling script had a line to abort when Project Accounting was installed. Removing Project Accounting and testing again proved that the code worked as expected without Project Accounting.
Digging further I found that Project Accounting had its own version of the same code that would trigger and replace the original core code which had been aborted. But in Service mode the trigger was not firing.
I located the trigger registration for this replacement code, but it was not in the Startup script (or a script called by Startup) as expected. Instead it was in a script triggered during the login process. Great, except that the login process for Service mode is different and so the triggers were never being registered.
The end result was that when Project Accounting was installed and you are running in Service mode, the original code aborted but the replacement code never executed.
To fix this, I check to see if Project is installed and call the project script to register the triggers from my script which triggers after the ServiceLogin global script. Once the missing triggers were registered in Service Mode, the rest of the code worked as expected.
Hopefully, this example shows how you can use GP Power Tools and Dynamic Trigger Logging to debug issues with Service Procedures.
Note: If you are a partner, you can request free NFR (Not for Resale) keys for GP Power Tools. For details see the GP Power Tools portal:
- GP Power Tools Portal: http://WinthropDC.com/GPPT
This article was originally posted on http://www.winthropdc.com/blog.