Wednesday, February 15, 2017

VST: An error occurred while loading or initializing an addin

As I mentioned before, I am now the Lead Software Engineer at Mekorma. I love it here as I get to work with some really talented software engineers and developers, all of which challenge me everyday. One of the cool new products we are working on, Mekorma Multi-Batch Management, allows you to build payment batches, print and post payments, and generate electronic funds transfer (EFT) and positive pay (Safe Pay) files, across companies, and across multiple checkbooks, with some minor configuration and just the click of a button. You can see an in-depth video on the product here.


Part of the challenges of building Multi-Batch Management were its extensive interfacing with both our own Mekorma MICR product and Microsoft Dynamics GP, and in particular, the Safe Pay module - Multi-Batch Management is designed to drive the Microsoft Dynamics GP user interface, thus eliminating the need for invasive code.

If you have worked on integrating code for Microsoft Dynamics GP, you are certainly familiar with the challenges surrounding the response to Dexterity modal dialogs. This is true for Microsoft Dexterity service enabled procedures as much as it is true for standard applications like ours, that simply try to drive the user interface.

NOTE: Dexterity does not have a programmatic mechanism to respond to modal dialogs. As it stands, only Visual Basic for Applications (VBA) and Visual Studio Tools for Microsoft Dynamics GP (VST) provide event handlers for modal dialogs.

VST aids in responding to Dexterity modal dialogs by allowing a developer to define form or window level modal event handlers. Because our code needed to respond to dialogs in Safe Pay only when our process was running, it was necessary to create an application assembly for our dictionary, that we could then reference in a Visual Studio Tools project. In addition, we needed to reference the Safe Pay application assembly as well. The project reference looks something like this:


Project References

Once references are added to the project, the tendency is to immediately add all event handlers to the Initialize() method within the GPAddIn class, as shown below:


public void Initialize()
{
   Dynamics.Forms.SyErrorMessage.SyErrorMessage.OpenBeforeOriginal += 
     Dynamics_SyErrorMessage_OpenBeforeOriginal;
   Dynamics.Forms.CmTransactionEntry.CmTransactionEntry.BeforeModalDialog += 
     Dynamics_BeforeModalDialog;
   Dynamics.Forms.CmEftGenerateFiles.CmEftGenerateFiles.BeforeModalDialog += 
     Dynamics_BeforeModalDialog;
   SafePay.Forms.MePpTransactions.MePpTransactions.BeforeModalDialog += 
     new EventHandler(SafePay_Transactions_BeforeModalDialog);
}


Unfortunately, this approach has a problem: let's assume Safe Pay is not installed, therefore, the Safe Pay application dictionary and application assembly are missing from the Dynamics GP installation folder. Since the Initialize() method is the entry point to your VST application, when the runtime engine attempts to load your assembly, your application would contain a reference to a non-existing assembly. This in turn will cause the runtime engine to produce the following error:

"An error occurred while loading or initializing an addin. As your administrator to check the Windows event log for more details. Dynamics will now close."


This is always been accepted as "the way things work". Unfortunately, we couldn't live with the status quo as it meant that customers who did not require the Safe Pay module would have to install it just for the sake of our assembly not failing.

We then attempted to move our event handler registration into it's own method, enveloping the call in a try..catch block:


public void Initialize()
{
   Dynamics.Forms.SyErrorMessage.SyErrorMessage.OpenBeforeOriginal += 
     Dynamics_SyErrorMessage_OpenBeforeOriginal;
   Dynamics.Forms.CmTransactionEntry.CmTransactionEntry.BeforeModalDialog += 
     Dynamics_BeforeModalDialog;
   Dynamics.Forms.CmEftGenerateFiles.CmEftGenerateFiles.BeforeModalDialog += 
     Dynamics_BeforeModalDialog;

   try 
   {
     InitializeSafePay();
   }
   catch (Exception e) 
   {
     throw new Exception(e.Message);
   }
} 

public void InitializeSafePay()
{
  SafePay.Forms.MePpTransactions.MePpTransactions.BeforeModalDialog += 
    new EventHandler(SafePay_Transactions_BeforeModalDialog);
}


The above produced virtually the same results. That is, the exception was still being displayed. Now, quite clearly, if we commented out the throw statement, the exception would no longer present itself and the message would not appear, precisely what we needed since we did not want to alert of the missing assembly and prevent the user from login into Dynamics GP.

NOTE: Alternatively, we implemented tracing capabilities for our assembly, so now all exceptions are recorded in a log file.

Special thanks to my Sr. Software Engineer, Lee Butenhoff for researching and providing a solution to this long standing issue.

Until next post!

MG.-
Mariano Gomez, MVP

2 comments:

Darren Woodbrey said...

Hi Mariano,

When driving the UI with VST, is there a way to hide the windows so the user does not see them opening and closing?

Darren

Mariano Gomez said...

Darren,

Whether you are using Dexterity or VST, the only known method is to move the windows off screen. This is, to a position greater than the current screen resolution.

MG.-
Mariano Gomez