#GPPT Referencing Modifier Added Fields in the Web Client using .Net Execute

David Meego - Click for blog homepageYou probably saw the recent article: Dynamics.Application Object not available on Web Client where I described an issue that was recently discovered and meant that the “Continuum” based triggers and scripts used to reference Modifier Added Fields in GP Power Tools – Developer Tools module were unable to work in the Web Client.

I mentioned a workaround that would function with the current GP Power Tools code when running on the Web Client (and Desktop Client). This article will show how you can use scripts in the .Net Execute Setup window to reference Modifier Added Fields.

The previous article described how the “Continuum” functionality to reference Modifier Added Fields using the Dynamics.Appplication COM Object is not available in the Web Client. But we do know that Visual Studio Tools code can work in the context of a Modified form and reference a Modifier Added Field. The trick is that you need to use the DAG.EXE (Dictionary Assembly Generator) tool to create a DLL which is the representation of the custom forms dictionary. When you add this DLL as a reference to your code it can be used by C# or VB.Net to access the Modifier Added Fields.

GP Power Tools has the ability to execute C# and VB.Net scripts already using the .Net Execute Setup window. So all we need to do is run the DAG.EXE tool on our Modified FORMS.DIC and then reference it in a .Net Execute script. The DAG.EXE tool is provided with Dexterity or with the Visual Studio Tools for Microsoft Dynamics GP SDK, or is included with Build 27.7 (15-Feb-2020) or later of GP Power Tools.

[Edit] The upcoming GP Power Tools Build 28 no longer uses “Continuum” and so no longer is affected by the limitations this caused.

We are going to use the example from the recent series of articles that started with #GPPT Beginner’s Guide to Adding Custom Fields – Introduction.

The steps involved from a high level are as follows:

  1. Create the Dictionary Assembly DLL of the Modified form with the DAG.EXE tool.
  2. Create .Net Execute Scripts to handle reading and writing of the Modified Added field.
  3. Create Triggers to call the .Net Execute Scripts for Save and Read events.
  4. Disable the previous Dexterity and “Continuum” based Triggers.

Please use the following steps to update the method used in the #GPPT Beginner’s Guide to Adding Custom Fields – Saving the data article to achieve the same result that is Web Client compatible. This is assuming that the window has been modified already.

Creating the Dictionary Assembly DLL

  1. While Microsoft Dynamics GP is not running, locate the Shortcut used to launch Microsoft Dynamics GP, right click on it and select Properties.
  2. Click Open File Location to open the Application folder in Windows Explorer. You should be able to find the DAG.EXE file. If not, update your GP Power Tools install or copy it from the Dexterity folder or the Visual Studio Tools SDK folder to the Application Folder.
  3. If the Application Folder is not under “C:\Program Files (x86)\” then you can right click on the folder in the left hand pane and select Command Prompt and then skip to Step 5.
  4. If it is under “C:\Program Files (x86)\”, then press the Window Key or Start Button and type CMD, right click on the CMD app displayed and select Run as Administrator and respond Yes to the UAC (User Access Control) prompt. Then copy the folder from the Start in field on the Properties window to the clipboard and use the CD (change directory) command to change to your Application folder.
  5. Using Windows Explorer, locate the Application.*.dll file for the product dictionary that you have modified. If there are Application.*.Metadata.dll and Application.*.Metadata.xml files for your product, copy them to another folder as a backup. Running the DAG tool will overwrite them and they will lose any digital signatures they previously had. I have reported this issue to Microsoft.
  6. If there is no Application.*.dll files for your product dictionary (Microsoft provides DLLs for all their dictionaries), then you will need to execute the DAG command from the command line to generate the Assembly for the main dictionary first, where XXX is the Dictionary ID listed in the DYNAMICS.SET launch file: DAG XXX DYNAMICS.SET /M
  7. Execute the DAG command from the command line. The DAG command used depends on which product dictionary the Modified form is located in. Below is the syntax needed for Dictionary 0 (Core Dynamics) using the launch file DYNAMICS.SET. As the core dictionary does not use the name of the file shown in the launch file (Application.Dynamics.dll rather than Application.MicrosoftDynamicsGP.dll) we will need to use the /N parameter to specify the name manually. The /F parameter is for Forms Dictionary and the /O is to overwrite an old version of the DLL file if it exists: DAG 0 DYNAMICS.SET /N:Dynamics /F /O
  8. Finally, if you made backup copies of Application.*.Metadata.dll and Application.*.Metadata.xml file, you can copy them back now.
  9. Type EXIT and press enter to close the command prompt window, and close the Properties window.

Creating the .Net Execute Scripts

  1. Launch Microsoft Dynamics GP and got to Project Setup for the project.
  2. Click Add >> .Net Execute Setup. Name the Script ID: ITEM URL READ, Script Name: Read Web URL Link field to Item Maintenance Window and Select Visual C# as the language.
  3. Click on the References Button and select Add Reference >> Browse for DLL file.  Select the Application.Dynamics.ModifiedForms.dll file and click OK.
  4. Remove the line with the MessageBox.Show()function. and leave your cursor in the blank space created.
  5. Use the Helper Button to insert the Get a DUOS Property helper function.
  6. Change the MBS_Object = “ID” line using the Names Button >> Forms to the Item Number of window IV_Item_Maintenance of form IV_Item_Maintenance field. The lookup will insert Dynamics.Forms.IvItemMaintenance.IvItemMaintenance.ItemNumber. Add .Value and make sure there is a semicolon at the end of the line (if it is missing*).
  7. On the line below which calls the DUOS helper function Microsoft.Dexterity.Applications.GpPowerTools.Procedures.MbsDuosGet.Invoke change the “Object” and “Property” to “Item” and “URL” respectively and add the keyword out before MBS_Property (if it is missing*).
  8. On the next line (currently blank), use the Names Lookup to add any local field. Change the name of the field at the end to LocalUrl. Change the dictionary at the start from Dynamics to DynamicsModifiedDictionary. Add .Value = MBS_Property; to complete the line.
  9. Click Save to check syntax and save the script.
  10. Now we can add the .Net version of the Script ID: ITEM URL SAVE, Script Name: Save Web URL Link field from Item Maintenance Window, Script Language: Visual C#.
  11. Click on the References Button and select Add Reference >> Browse for DLL file.  Select the Application.Dynamics.ModifiedForms.dll file and click OK.
  12. Remove the line with the MessageBox.Show()function. and leave your cursor in the blank space created. Then use the Helper Button to add the Set a DUOS Property helper function and below that use the Helper Button again to add the Delete a DUOS Property helper function.
  13. Change the MBS_Object = “ID” line using the Names Button >> Forms to the Item Number of window IV_Item_Maintenance of form IV_Item_Maintenance field. The lookup will insert Dynamics.Forms.IvItemMaintenance.IvItemMaintenance.ItemNumber. Add .Value and make sure there is a semicolon at the end of the line (if it is missing*).
  14. Change the MBS_Property = “Value” line using the Names Lookup to add any local field. Change the name of the field at the end to LocalUrl. Change the dictionary at the start from Dynamics to DynamicsModifiedDictionary. Add .Value and make sure there is a semicolon at the end of the line (if it is missing*).
  15. For the two calls to the DUOS helper functions Microsoft.Dexterity.Applications.GpPowerTools.Procedures.MbsDuosSet.Invoke and Microsoft.Dexterity.Applications.GpPowerTools.Procedures.MbsDuosDel.Invoke change the “Object” and “Property” to “Item” and “URL” respectively.
  16. Remove the two lines with the second declaration of the MBS_Object.
  17. Now add an if statement to check if the MBS_Property variable has data in it and either save or delete the DUOS property accordingly.
  18. Click Save to check syntax and save the script. You can close the .Net Execute Window and return to Project Setup.

* I will fix the missing bits from the inserted helper function code in an upcoming build.

Calling the .Net Execute Scripts from Triggers

  1. From the Project Setup Window, double click on the ITEM URL READ Trigger to open it. Click Duplicate and Name it ITEM URL READ2 and click OK.
  2. No changes are needed on the Resource, Actions or Options tabs. Click on the Script Tab. Uncheck the Modified and Check Security checkboxes. This will reset the script.
  3. Remove the if not empty and end if lines, but leave the OUT_Condition line. Leave some blank lines to insert the helper functions to call the .Net Execute script.
  4. Use the Helper button to add the Load .Net Execute Script ID helper function for the script ITEM URL READ. Then below the inserted lines use the Helper button again to add the Execute .Net Script helper function.
  5. As we have loaded the MBS_Mode, MBS_References, and MBS_Script variables with the first helper function we can delete the example lines added by the second helper function. We can also clean up the formatting by indenting the helper functions calls and removing the extra lines.
  6. This code works, but it will also execute for the original window and so throw an exception as the .Net Execute script will not be able to find the Modifier added field. So place your cursor below the if isopen(form line and use the Helper Button to add the Check Form Security helper function for the IV_Item_Maintenance form.
  7. Cut and paste the end if; line to move it to below the other helper functions and indent the existing helper function calls code. Now the code will only run if the Modified window is in use.
  8. Click Save to save the Trigger.
  9. From the Project Setup Window, double click on the ITEM URL SAVE Trigger to open it. Click Duplicate and Name it ITEM URL SAVE2 and click OK. No changes are needed on the Resource, Actions or Options tabs. Click on the Script Tab. Uncheck the Modified and Check Security checkboxes. This will reset the script.
  10. Repeat the above steps for the ITEM URL SAVE Trigger to create the ITEM URL SAVE2 Trigger which calls the ITEM URL SAVE .Net Execute Script. The only difference is to leave the if not empty(‘Save Record’) statement, but remove the empty() function, move the OUT Condition down outside the if statement and add abort script;
  11. Now add the three helper functions: Check Form Security for IV_Item_Maintenance form, Load .Net Execute Script ID for ITEM URL SAVE script and Execute .Net Script.
  12. Click Save to save the Trigger and close the window.

Disabling the original Triggers

  1. From the Project Setup window. Double click on the ITEM URL READ Trigger. Once open, select the Disabled checkbox and click Save.
  2. From the Project Setup window. Double click on the ITEM URL SAVE Trigger. Once open, select the Disabled checkbox and click Save.
  3. Close the Trigger Setup window.
  4. From the Project Setup window, click Start >> Start Project Triggers and test the Modified version of the Item Maintenance window on the Desktop Client. Once you are happy it is working, re-test on the Web Client.

Below is the code from the two.Net Execute Scripts:

ITEM URL READ .Net Execute Script

using System;
using System.Windows.Forms;
using Microsoft.Dexterity.Bridge;
using Microsoft.Dexterity.Applications;
using Microsoft.Dexterity.Applications.DynamicsDictionary;
using Microsoft.Dexterity.Applications.DynamicsModifiedDictionary;
using Microsoft.Dexterity.Applications.GpPowerToolsDictionary;

namespace NetExecute
{
	public class Program
	{
		public void Run( )
		{
			// Add your code below this line
			
			string MBS_ObjectID = "";
			string MBS_Property = "";
			MBS_ObjectID = Dynamics.Forms.IvItemMaintenance.IvItemMaintenance.ItemNumber.Value;
			Microsoft.Dexterity.Applications.GpPowerTools.Procedures.MbsDuosGet.Invoke("Item", MBS_ObjectID, "URL", out MBS_Property);
			
			DynamicsModified.Forms.IvItemMaintenance.IvItemMaintenance.LocalUrl.Value = MBS_Property;
			
			// Add your code above this line
		}
	}
}

ITEM URL SAVE .Net Execute Script

using System;
using System.Windows.Forms;
using Microsoft.Dexterity.Bridge;
using Microsoft.Dexterity.Applications;
using Microsoft.Dexterity.Applications.DynamicsDictionary;
using Microsoft.Dexterity.Applications.DynamicsModifiedDictionary;
using Microsoft.Dexterity.Applications.GpPowerToolsDictionary;

namespace NetExecute
{
	public class Program
	{
		public void Run( )
		{
			// Add your code below this line

			string MBS_ObjectID = "";
			string MBS_Property = "";
			MBS_ObjectID = Dynamics.Forms.IvItemMaintenance.IvItemMaintenance.ItemNumber.Value;
			MBS_Property = DynamicsModified.Forms.IvItemMaintenance.IvItemMaintenance.LocalUrl.Value;
			if (MBS_Property != "")
			{
				Microsoft.Dexterity.Applications.GpPowerTools.Procedures.MbsDuosSet.Invoke("Item", MBS_ObjectID, "URL", MBS_Property);
			}
			else
			{
				Microsoft.Dexterity.Applications.GpPowerTools.Procedures.MbsDuosDel.Invoke("Item", MBS_ObjectID, "URL");
			}

			// Add your code above this line
		}
	}
}

Below is the code from the two new Trigger scripts:

ITEM URL READ2 Trigger Script

in string IN_OldValue;
in string IN_NewValue;
out boolean OUT_Condition;
local integer MBS_Mode;
local text MBS_References;
local text MBS_Script;
local text MBS_Results;
local boolean MBS_Success;
local boolean MBS_Access;
local integer MBS_AltDictID;
local boolean MBS_Modified;

OUT_Condition = false;

if isopen(form IV_Item_Maintenance) then
	call with name "MBS_Security_Form_Check" in dictionary 5261, 0, "IV_Item_Maintenance" {Form}, 
		MBS_Access, MBS_AltDictID, MBS_Modified;
	if MBS_Access and MBS_AltDictID = 0 {Product} and MBS_Modified then 
		{ Code in here } 
		call with name "MBS_Script_Load_Net" in dictionary 5261, 
			"ITEM URL READ", MBS_Mode, MBS_References, MBS_Script;

		MBS_Success = false;
		call with name "MBS_Net_Execute" in dictionary 5261, 
			MBS_Mode, MBS_References, MBS_Script, MBS_Results, MBS_Success;
		if not MBS_Success then
			warning MBS_Results;
		end if;
		OUT_Condition = true;
	end if;
end if;

ITEM URL SAVE2 Trigger Script

in string IN_OldValue;
in string IN_NewValue;
out boolean OUT_Condition;
local boolean MBS_Access;
local integer MBS_AltDictID;
local boolean MBS_Modified;
local integer MBS_Mode;
local text MBS_References;
local text MBS_Script;
local text MBS_Results;
local boolean MBS_Success;

OUT_Condition = false;

if isopen(form IV_Item_Maintenance) then
	if not 'Save Record' of window IV_Item_Maintenance of form IV_Item_Maintenance then
		abort script;
	end if;

	call with name "MBS_Security_Form_Check" in dictionary 5261, 0, "IV_Item_Maintenance" {Form}, 
		MBS_Access, MBS_AltDictID, MBS_Modified;
	if MBS_Access and MBS_AltDictID = 0 {Product} and MBS_Modified then 
		{ Code in here } 
		call with name "MBS_Script_Load_Net" in dictionary 5261, 
			"ITEM URL SAVE", MBS_Mode, MBS_References, MBS_Script;

		MBS_Success = false;
		call with name "MBS_Net_Execute" in dictionary 5261, 
			MBS_Mode, MBS_References, MBS_Script, MBS_Results, MBS_Success;
		if not MBS_Success then
			warning MBS_Results;
		end if;
		OUT_Condition = true;
	end if;
end if;

This method resolves the issue of scripting against a Modifier Added Field. I am still working on a solution to create triggers or events against a Modifier Added Field or Modal Dialog. Note that currently the triggers used to make the hidden hyperlink button open the URL and the checking of the URL formatting are not functioning in the Web Client.

Here is the updated exported Configuration Settings file for the example:

Thanks to Arthur Achilleos for reminding me of this technique.

Please note that in a future build of GP Power Tools, many of these steps will be automated and simplified. This article was to show how it works with the already released build 27.7 of GP Power Tools.

Hope you find this information useful.

David

08-Apr-2020: Added comment that GP Power Tools Build 28 no longer uses “Continuum”.

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

3 thoughts on “#GPPT Referencing Modifier Added Fields in the Web Client using .Net Execute

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.