#GPPT Forcing Exclusive Use of Microsoft Dynamics GP Windows

David Meego - Click for blog homepageI was recently informed of an issue that a Microsoft Dynamics GP customer site was facing where having more than one user in a particular window at the same time was causing issues.

While the issue has been logged with Microsoft Support, the fix will not be available for a while, so I was asked how easy would it be to force the window to only work exclusively for a single user at a time using GP Power Tools.

The answer…. very easy …. initially.

Microsoft Dynamics GP already has a resource activity tracking system built in that developers can use to control access to windows or other resources. The calls are used in a number of GP Power Tools windows to ensure exclusive use. The advantage of using this system is that it is automatically cleaned up if a session has a catastrophic unplanned exit (AKA GP crashed).

First Version

To re-use the same activity tracking code was very simple for a window in the core Dynamics.dic dictionary. After creating a Project to group everything together, I just needed a couple of triggers to make this work for each Dexterity form in question:

  • A focus trigger before the FORM PRE event to check the activity and set the activity record if none already exists using the SetResourceState() of form ResourceActivity form level function. This trigger will close the form after displaying a message if it is already in use.
  • A focus trigger after the WIN POST event to clear the activity record using the ClearActivity of form ResourceActivity form level procedure.

To make the functionality more user friendly (read useful), some additional code was added to read the activity table when another user was already in the window to obtain the User ID so it can be displayed on the message. This was achieved by creating a range on the table SY_ResourceActivity and getting the first (and only) record in that range.

The first version of this code worked fine for a core window such as Customer Maintenance (RM_Customer_Maintenance) but failed to compile when trying to apply the same code to a window in a third party Dexterity dictionary.

[Edit] I am using the Customer Maintenance window as an example to test the concept, there is no issue with this window. I will post more details on the actual issue with a new project as required once we have a tested solution.

Note: In Dexterity a third party dictionary is any dictionary other than the core Dynamics.dic and it might be provided by Microsoft, an ISV (Independent Software Vendor) or a customization written by a partner or consultant.

Second Version

The issue is that the trigger itself and the handler script need to be in the context of the dictionary that contains the window, but the calls to the resource activity tracking code need to be in the context of Dynamics.dic (dictionary 0).

To solve this the calls to the activity tracking scripts were placed into two Runtime Execute scripts which could then be loaded and called by the trigger handler scripts. This method allows scripts running in the context of one dictionary and to then call code running in the context of another dictionary.

Finally, to pass data or parameters between the scripts GP Power Tools has three methods available. All three methods are implemented using GPPT Helper Functions. We can use either

  1. the original “old style” table based Parameters which use strings in the DUOS (Dynamic User Object Store) table (implemented as the SY90000 table in SQL),
  2. the newer memory based Parameters which don’t use tables and have different datatypes available, or
  3. a Parameter List with values defined as needed.

I decided on the Parameter List approach for a number of reasons:

  • Parameter List values are automatically substituted into the script code before the script runs.
  • Parameter List variables don’t need to be cleaned up (deleted) after use.
  • Parameter Lists can be used with an interface when testing code, but not displayed in the final code.
  • Parameter List variables can read (set) and written (get) in code instead of entered by a user.
  • Default values for the Parameter List variables can be entered to make testing easier.

So now we could test the Runtime Execute Scripts with the default parameters to make sure it works.

The Set Window script clears the return Parameter List variable (Active) then uses the standard call to check and set the activity record. If the window is in use, it gets the User ID, displays a message and sets the return Parameter List variable to true.  When testing, this script will show the warning dialog when it is executed for the second or subsequent times.

Note: Normally the second parameter to the SetResourceState() of form ResourceActivity call is just the technical name of the form. To ensure a unique value regardless of dictionary, I have prefixed it with the Dictionary ID as a string. This can be seen in the script with the two Parameter List placeholders: str(0{%01%})+””{%02%}.

The Clear Window script just removes the activity record if it exists, thus allowing the Set Window script to run again without the warning dialog being displayed.

Now we can have the two triggers for each window which just load the Parameter List and set the values before loading and calling the Runtime Execute Scripts.

The before FORM PRE trigger which calls the Set Window Runtime Execute script and close the form if the window is already active.

The after WIN POST trigger which calls the Clear Window Runtime Execute script.

Finally, here is the Project Setup which holds all the components together and allows them to be exported and imported as a single file.

Downloading and Installing

Download the example code, import using the Configuration Export/Import window:

Installing the sample code:

  • If this is the first time importing the project use the Configuration Export/Import window (GP Power Tools >> Routines >> Configuration Export/Import). Select the file and click Import. Then click OK on the confirmation window.
  • If the project already exists, use the Project Setup window instead. Select the file and click Import. Then click OK on the confirmation window.
  • The code will be active on next login or after switching companies, or you can use start them manually from the Project Setup window.

Implementing for other windows

To add this functionality to other windows, you will need to duplicate the two triggers for each window and change the dictionary, form and window as required.  Cut and paste the scripts from the sample triggers and find and replace the form and window names.

After duplicating the trigger, copy the script to the clipboard before changing the details of the resource, this way you can paste it back before finding and replacing the form and window names.

[Edit] For the first “Form Level” trigger go to the Action Tab and ensure that the Issue Reject Script checkbox is selected. When you change the trigger’s resource information, this option might become unchecked. This is needed to ensure that the form’s code doesn’t try to run after we have closed the form.

Note: Use Ctrl-R (for Replace) and Ctrl-B (for Replace Next). The form name and window name are usually, but not always the same. Make sure that when the command is referring to the window to use the window name if it is different. The script will fail to compile if the Window name is incorrect, you can use the Names >> Forms, Windows & Fields button on the Script tab or the lookup button the Resource tab to check window names.

More Information

For more information see:

David

31-May-2021: Added note explaining there was no issue with the Customer Maintenance window, it was just used as an example.
04-Jun-2021: Added note about making sure the Issue Reject Script checkbox is selected on the first trigger. The download has been updated to hide the Active parameter and enable this checkbox.

This article was originally posted on http://www.winthropdc.com/blog.

Please post feedback or comments

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.