Automating the start and stop of Microsoft Dynamics GP logs with the Support Debugging Tool – Part 2

July 28, 2011

Yesterday, we tackled the first part of this Support Debugging Tool project, showing how to implement the logging trigger portion. To recap, the application logging files (DEXSQL.LOG and Dexterity Script Log) will begin to record when the Hold checkbox on the Vendor Maintenance window is marked. However, registering the logging trigger will only occur when the Vendor Maintenance form is opened, and unregister, when the Vendor Maintenance form is closed. This will provide an effective set of actions to be recorded as opposed to logging every single action that occurs within the application.

Now that we have implemented the logging portion, we need the two non-logging triggers: the trigger that will start the logging trigger, and the one that will stop it.

The Start Trigger

We will start by setting up the non-logging trigger that will activate the VEND_HOLD_CHG logging trigger (which in turn will begin logging only when the Hold checkbox is marked). We will want to attach this trigger to the Vendor Maintenance form PRE script. We want the logging trigger to register once the Microsoft Dynamics GP code has run, hence we will startup the logging trigger after the original event. Unlike the logging trigger, this trigger start automatically upon the user launching and login into Microsoft Dynamics GP.

ST_VENDHOLD_LOG non-logging trigger – Resource tab

We will move to the Script tab and use a Helper function to assist with adding the code that will start up the logging trigger. By clicking on the Helper button, the Insert Helper Function window displays, from where we can choose the Start an Automatic Mode Trigger ID option in the drop-down list.

Insert Helper Function window

Then we can move to select the logging trigger ID, VEND_HOLD_CHG created previously.

Again, the Support Debugging Tool does most of the sanScript coding needed for this purpose by calling the built-in API procedure MBS_Trigger_Start to start up our VEND_HOLD_CHG trigger. Very convenient!

ST_VENDHOLD_LOG non-logging trigger – Script tab

Next we need to setup the non-logging trigger to disable the logging trigger.

The Stop Trigger

For this case, and instead of trying to replicate all these setups, we can take advantage of the Duplicate button of the Automatic Debugger Mode setup window to create a copy of the start up trigger.

Duplicate Button

Finally, we adjust the non-logging trigger to fire after the Vendor Maintenance form post script has executed, and change its script to call the MBS_Trigger_Stop Support Debugging Tool API function to un-register the VEND_HOLD_CHG trigger, effectively stopping all logging.

EN_VENDHOLD_LOG non-logging trigger

Now is time to turn on our non-logging triggers (which are set to start up automatically on login in into the Microsoft Dynamics GP application).

Turning on non-logging automatic start only triggers

A look the Automatic Debugger Mode status window shows our non-logging triggers waiting for the Vendor Maintenance window to open.

Automatic Debugger Mode Status window

If we open the Vendor Maintenance window we will see our trigger VEND_HOLD_CHG trigger is automatically registered (along with a secondary trigger that captures the original value of the field prior to being selected so it can be restored if needed). The Support Debugging Tool main window will change the color and prompt of the Automatic Debugger Mode button. When the Hold checkbox is marked, the logging trigger activates the logs and displays the desktop alert.

And all of this occurred without the end-user’s intervention. In addition, the DEXSQL.LOG and Script Log files will only contain all events that occurred while the window was opened and records were manipulated. Once the Vendor Maintenance window was closed, the logs were suspended.

I have attached the configuration file to be imported with the Support Debugging Tool’s Configuration Export/Import window. Once you import the XML file just activate the non-logging triggers as indicated above and you should be good to go.

Vendor Hold triggers – VEND_HOLD.zip

Discover the power of the Support Debugging Tool.

Until next post!

MG.-
Mariano Gomez, MVP
IntellPartners, LLC
http://www.IntellPartners.com/


Automating the start and stop of Microsoft Dynamics GP logs with the Support Debugging Tool – Part 1

July 27, 2011

If you haven’t noticed, it is – unofficially, of course – Support Debugging Tool week. With the fairly recent release of build 15 and a revision of that build, the tool has just gotten better with heaps of new features and improvements over existing ones! And I am exploring some really cool stuff that can be done with the product. Yesterday I showed how you can use the Automatic Debugger Mode’s non-logging trigger capabilities to Default “Include Totals and Deposits” in the Sales Transfer Entry window

Today, I will touch on the topic of Automatic Debugger Mode and non-logging triggers again. However, this time I will show how you can use non-logging triggers in combination with logging triggers to capture vital application logs upon the occurrence of some Microsoft Dynamics GP application event without user intervention.

This may sound a little esoteric, but the concept is simple. For this example we will use the Vendor Maintenance window, a very familiar window to most of you who interact with Microsoft Dynamics GP on a daily basis.

Vendor Maintenance

For this example, we will register two non-logging triggers on the Vendor Maintenance form: the first non-logging trigger will start up a logging trigger that initiate application events logging – DEXSQL.LOG and Dexterity Script Log for this example – when the Hold checkbox is activated. The second non-logging trigger will stop the logging trigger upon closing the Vendor Maintenance form.

Think of the advantages of this for a second… imagine a user who has been experiencing a random issue for quite some time in a window and the data being processed in that window. It would be fantastic if you could turn on and turn off Microsoft Dynamics GP logs upon certain event (or events) happening on that window without the user having to be aware or have the presence of mind to do this himself/herself. This certainly would make the process of troubleshooting quite simple, less intrusive, and more precise!

So let’s take a look at what is required:

1. A logging trigger that activates our DEXSQL.LOG and Dexterity Script Log when the hold checbox is marked.

2. A non-logging trigger that will register the above logging trigger when the Vendor Maintenance form is opened.

3. A non-logging trigger that will un-register the logging trigger in number 1 when the Vendor Maintenance form is closed.

The Logging Trigger

We will start by setting up the logging trigger that will activate only when the Hold checkbox is marked. The trigger type in this case is a Focus Event and will only fire when the field changes, that is, when is marked – conceivably, you could add code that deals with the event of unmarking the checkbox. We want any action to begin once the Microsoft Dynamics GP code has run on that field, hence we will initiate our logs after the original event. Note also, this trigger will not start automatically upon the user launching and login into Microsoft Dynamics GP, since we only want this to happen when the Vendor Maintenance form is opened – and stop when it is closed.

VEND_HOLD_CHG trigger – Resource tab

On the Actions tab, we will just send a desktop alert to the end user by choosing the respective option.

VEND_HOLD_CHG trigger – Actions tab

The beauty of the Support Debugging Tool is, you really need little in the form of Dexterity development knowledge and probably just an understanding of basic programmatic constructs to follow along and complement the helper functions. See, while you were fiddling with the setup options for the trigger in the Resource tab, the Support Debugging Tool was putting together some code for you based on your selections.

VEND_HOLD_CHG trigger – Script tab

Since we want the logs to be captured when the Hold checkbox is marked then the helper function seems just adequate. This means, no need to really have to add more code – unless, of course, there’s something else you would like to achieve beyond what’s already given in the helper code.  Remember, the code is Dexterity sanScript code.

Finally, for this logging trigger, we want to, well, log something. For that we go to the Options tab.

VEND_HOLD_CHG logging trigger – Options tab

In this tab, we will want to choose the DEXSQL.LOG and the Dexterity Script Log. If you suspect performance issues, you can activate the Dexterity Script Profiler – see How to read a Dexterity Script Profile to solve Performance Issues over at Developing for Dynamics GP for more information on this.

That’s it! This easy! Our logging trigger is ready and now we will just need the non-logging triggers to start and stop it – in Dexterity parlance, register and unregister it.

Tomorrow, I will walk you through setting up the non-logging triggers that will start up this one and show some more cool helper functions. You will also have links to download the configuration files for this SDT project. For now, go and grab the Support Debugging Tool if you haven’t done so yet.

Until next post!

MG.-
Mariano Gomez, MVP
IntellPartners, LLC
http://www.IntellPartners.com/


Defaulting "Include Totals and Deposits" in Sales Transfer Entry with the Support Debugging Tool

July 26, 2011

More times than I care to count I have been called in to fix records left behind because the Include Totals and Deposits option was not marked when transferring a sales document from an existing order to an invoice. The problem is, it is so easy to forget to mark that box if you are doing this for hundreds of transactions fractured in multiple batches, especially at the end of the week when invoices need to be submitted to customers, prior to the FedEx truck arriving at 4:00 PM.

Sales Transfer Documents window

While this “fix” has been provided as a Modifier with VBA project before, I thought, why not really prop this up a bit with a Support Debugging Tool non-logging trigger and take advantage of the Automatic Debugger Mode functionality? Well, I have done just that!

The first thing we need to do is setup the trigger itself. In this case, we want to select a Focus Event trigger that will fire exactly on a field change condition. The field in question is the ‘(L) Order To Invoice CB’ checkbox field. You can use the lookup button next to the Form Name field on the Resource tab to open the Support Debugging Tool’s Resource Explorer window and locate the field and select it.

Trigger Setup

Since this will be a non-logging trigger, we will want to check the Do not activate Logging Mode option on the window. And to make sure the trigger always starts up with Microsoft Dynamics GP, we will want to check the Start Trigger Automatically on Login option as well.

Second, we can choose to have the Support Debugging Tool perform certain actions when the event fires – the event being when the checkbox is marked. If you happen to be running build 15 of the SDT, you can have a message display as a desktop alert on the lower right corner of your screen, similar to when you receive a Microsoft Outlook message.

For the purpose of this trigger, we will not take any actions when the trigger fires.

Third, we must add the processing script. The Support Debugging Tool does a really good job at providing a helper to build upon. So all we need to do is add the little bit to process the Include Totals and Deposits checkbox field, after the Transfer to Invoice checkbox has been marked. This is the final script:

Trigger processing script

Finally, since this is a non-logging trigger, the Options tab will show all logging options disabled. However, you can still choose a date range for this trigger to take effect.

Options tab

Since the goal is to have this trigger available at all times, there’s no need to add a start and end date. It’s now time to save the trigger and enable it.

We can choose to turn on our Non Logging Automatic Start Only triggers. Since our SOP_XFER trigger has been marked as a non-logging automatic trigger we should be able to see it in the Automatic Debugger Mode Status window.

Automatic Debugger Mode Status window

This is really all there is to it! The trigger should now cause the Include Totals and Deposits checkbox to activate automatically when we choose the Orders to Invoices checkbox.

I have attached the configuration file to be imported with the Support Debugging Tool’s Configuration Export/Import window. Once you import the XML file just activate your trigger as indicated above and you should be good to go. No more forgetting to mark Include Totals and Deposits when transferring orders to invoices.

Include Totals and Deposits trigger – SOP_XFER.zip

The Support Debugging Tool’s non-logging triggers functionality is a very powerful way to deploy simple scripts that can take care of every day headaches. All you need is a bit of creativity and the tool itself – see David Musgrave’s article Support Debugging Tool Build 15 released for more on the latest Support Debugging Tool build.

Until next post!

MG.-
Mariano Gomez, MVP
IntellPartners, LLC
http://www.IntellPartners.com/


Passing arrays as parameters to functions or procedures in Dexterity

June 23, 2011

First, some theory…

The individual pieces that make up an array are called elements. The elements are numbered from 1 to the size of the array. Arrays can have up to 32,767 elements. The number used to indicate a specific element of the array is called the array index. A specific element of the array is referenced in sanScript using its corresponding array index.

Typically, an array can be used in place of several fields that have the same data type and will be storing similar information. For example, if an application keeps track of monthly sales for a year, one monthly sales array field with an array size of 12 could be used to store this information instead of 12 separate fields.

Dexterity applications can use array fields [in tables] and array local variables [in memory]. Array fields are created in the Field Definition window by setting the Array Size field to the size of the array. Array local variables are created by including the size of the array in brackets – [ ] – following the local variable name. When creating local arrays, the array size must be a constant expression. Array sizes can’t be set at runtime.

To access the elements of an array from within a script, simply use the name of the array and add the index number of the element you want to reference. Be sure the index number is included in square brackets after the name of the array and before the qualifier. The following example sets the third element of the Quarterly Sales array field (corresponding to the third quarter) to the sum of the monthly sales for July, August and September.

'Quarterly Sales'[3] = 'Jul Sales' + 'Aug Sales' + 'Sep Sales';

The following example uses a local array field with five elements to act as status flags for the script. The for loop initializes the flags to false.

local boolean status[5];
local integer i;

for i = 1 to 5 do
status[i] = false;
end for;

Now to the problem…

A couple days aback a developer reported issues when passing an array as a parameter to a Dex global procedure – won’t have been any different for a function either. Her code was as follows – I say was as I assumed it has been fixed since.

local currency l_plan_total, l_month_totals[13];

call TAS_Calculate_Plan_Totals,
'Customer Number' of table TAS_Plan_Header,
Year of table TAS_Plan_Header,
TAS_Plan_Status of table TAS_Plan_Header,
'Revision Number' of table TAS_Plan_Header,
l_plan_total,
l_month_totals[13];

The procedure signature is as follows:

{PROC: TAS_Calculate_Plan_Totals}

in string i_customer;
in integer i_year, i_status;
in long i_revision;
out currency o_total;
out currency o_month[13];

local currency l_month[13];

Things to note… in the calling script, the developer declares an array of monthly totals of 13 elements, then calls the TAS_Calculate_Plan_Totals passing the array as a parameter. The procedure is pretty straight forward and uses an out parameter to pass-back whatever results the developer will calculate and put into each element of the array.

However, when the code is compiled, the developer receives the error type incompatibility on parameter #6. That happens to be the array parameter in the call to the global proc.

Taking a closer look, the developer is passing l_month_totals[13] to in the procedure call. Since, the parameter in the procedure has been declared as an array, l_month_totals[13] is being interpreted by the Dexterity compiler as the currency value represented by the element with an index of 13. In other words, just the plain currency value and not the array as a whole. To correct the code, the developer needed to remove the brackets from the call, just passing l_month_totals, as follows:

local currency l_plan_total, l_month_totals[13];

call TAS_Calculate_Plan_Totals,
'Customer Number' of table TAS_Plan_Header,
Year of table TAS_Plan_Header,
TAS_Plan_Status of table TAS_Plan_Header,
'Revision Number' of table TAS_Plan_Header,
l_plan_total,
l_month_totals;

{PROC: TAS_Calculate_Plan_Totals}

in string i_customer;
in integer i_year, i_status;
in long i_revision;
out currency o_total;
out currency o_month[13];
local currency l_month[13];

I must say that the developer in question is an experienced developer, but at the same time, I can see how this can become confusing even for the experts. I personally believe that a better approach for this call – talking to you Dex compiler gurus in Fargo – would have been as follows:

call TAS_Calculate_Plan_Totals,
'Customer Number' of table TAS_Plan_Header,
Year of table TAS_Plan_Header,
TAS_Plan_Status of table TAS_Plan_Header,
'Revision Number' of table TAS_Plan_Header,
l_plan_total,
l_month_totals[];

Note the use of the brackets as a way to differentiate the array variable from, say, the other currency variable just above it. On that same note, I have a long list of suggested compiler changes for Dexterity, but I am sure these are not a priority at this point.

Until next post!

MG.-
Mariano Gomez, MVP
IntellPartners, LLC
http://www.IntellPartners.com/


Microsoft Dynamics GP "12" Web Client Architecture – Part 3

May 16, 2011

This is article 3 of 3 from the series Microsoft Dynamics GP “12” Web Client Architecture. Some images and content reproduced with express permission from Microsoft Business Solutions, a division of Microsoft Corporation.


In Part 2 we explored the Microsoft Dynamics GP “12” Web Client’s Rendering Engine and how it had to be decoupled from the overall Dexterity Runtime Engine functions, in order to create a Generic Window Object that could be rendered as a Windows Form or a Silverlight interface.

Today this article discusses how a Generic Window Object is transformed into a Windows form or a Silverlight UI, but before, let’s remember that the Window Manager, a former part of the Dexterity Runtime Engine, is still in charge of processing the UI events while  the Rendering Engine presents the interface to the end-user.

Dynamic Form Rendering with Template Processor

Now that the Dexterity Runtime Engine has been freed of these tasks, the resulting Generic Window Object must be processed to produce either interfaces. For this, the Development team has created Template Processor.

Template Processor takes a generic representation of a window and is able to deliver an XML version of its content (fields, buttons, and events in the case of a traditional Dexterity window), called a Window Template, but as well delivers a version that the Dexterity Runtime Engine can still display in the classical client, also known as coreTemplate. The technique of processing a Generic Window Object into an XML Window Tempalte and a coreTemplate has been labeled Dynamics Form Rendering.

The XML Window Template is then delivered to Silverlight via a browser application – explicitly Internet Explorer given the use of Silverlight – where the Rendering Engine uses a Converter to serialize into a Silverlight UI. Since the Dexterity Runtime Engine retains the ability to understand the coreTemplate elements, displaying a Windows form is still a natural function.

Dynamic Form Rendering – Developer’s Experience

The result will still allow developers to create traditional Dexterity customizations against the classic client UI or the XML Window Template generated by the Template Processor.

On a closing note, GP “12” aims to provide additional deployment methods to the traditional classical client deployment, where the client is either delivered as an installation at desktop level or in a Terminal Server or Citrix environment. With the Silverlight client, users can rely on their Internet Explorer browser and the Silverlight plug-in to run their Microsoft Dynamics GP application, while retaining the feature rich functionality of the classical client.

To make things even more interesting, a deployment environment can take advantage of both the classical client and the Silverlight client at the same time. Why would you need both? I suspect certain application functions like maintenance are best executed from the classical client, however in the scheme of things, it allows for a smooth end-user transition.

Finally, I hope you enjoyed this series of articles and I will continue to work with the Microsoft Dynamics GP Product Management team to deliver information to you as it becomes available (and needless to say, not deemed a trade secret). There is more to all this than meet the eyes.

Until next post!

MG.-
Mariano Gomez, MVP
IntellPartners, LLC
http://www.IntellPartners.com/


Microsoft Dynamics GP "12" Web Client Architecture – Part 2

May 11, 2011

This is article 2 of 3 from the series Microsoft Dynamics GP “12” Web Client Architecture. Some images and content reproduced with express permission from Microsoft Business Solutions, a division of Microsoft Corporation.


In Part 1 of this series I went through the architecture transition from the classic client (the traditional Microsoft Dexterity interface and its evolution) to the Microsoft Dynamics GP “12” Web Client and introduced some elements of that architecture (Silverlight, .NET C#, and .NET Runtime) and how these elements fall into the “Built to Last” philosophy outlined in the overall Architectural Foundation.

Today, this article will continue down the lines outlining some of the technology challenges posed by the introduction of the Web Client and the highlighting some of the radical changes (from a development perspective) needed at the core of Microsoft Dexterity and Microsoft Dynamics GP to enable the Microsoft Silverlight interface.

The Rendering Engine

If you are a Microsoft Dexterity developer, you are already in tune with the purpose of forms (windows in the general sense) as an essential part of any Microsoft Dexterity application or integrating solution. After all, there are a key mechanism by which a user will interact with the Microsoft Dynamics GP system.

As such, a Microsoft Dexterity window typically includes sanScript code associated to the controls on that window. This code executes in response to events given the intended function of the window and the controls, i.e., save a transaction, post a batch, etc., under the direction of the Script Interpreter.

Note: The process of chunking a dictionary typically involves the removal of source code for shipping of the dictionary. Hence the need for the Script Interpreter as an integral component of the Runtime Engine.

Under the hood though, the user interface is administered by the Window Manager, which in turn talks to the Rendering Engine to display the actual Microsoft Dexterity window on the screen with the control elements previously laid out by the developer.

Web Client Architecture

The tight bond between UI and code has served well up to now, but it hasn’t been without its drawbacks. One of the biggest complaints registered by developers and users alike is the fact that too much of the Microsoft Dynamics GP code resides within the user interface and the confines of the dictionary which makes for a heavy client – nonetheless, fitting the traditional client/server application architecture.

To facilitate the transition to the Web Client, the Window Manager and Rendering Engine have been decoupled from the functions of the Runtime Engine, allowing the Microsoft Dexterity Runtime Engine to produce a Generic Window Object instead. With a generic window, a classic client can continue to serve up the typical Win32 forms all the while allowing a Silverlight client to serve up a web based representation of that form. Decoupling the Window Manager and Rendering Engine allows for forms to move freely between the Win32 and Web worlds with the help of another key piece of technology – more on this in the next installment.

With the Window Manager and Rendering Engine decoupled, you can now conclude that a Microsoft Dexterity application can run as a service in the background, awaiting for events that would be either received via a traditional Win32 form or a Silverlight client, and STILL be able to execute script events regardless of the type of form they were submitted through. The theory also would indicate that a Microsoft Dexterity application is the basis for a Web Client version of itself. This is, a Microsoft Dexterity applications can leverage the new architecture elements to become web enabled – but not the other way around (yet!).

But how is the classic UI transformed into a web version? In the next and final installment, I will dig a bit more into the patent worthy elements of the architecture: Template Processor and Dynamic Window Rendering.

Until next post!

MG.-
Mariano Gomez, MVP
IntellPartners, LLC
http://www.IntellPartners.com/


Microsoft Dynamics GP "12" Web Client Architecture – Part 1

May 9, 2011

This is article 1 of 3 from the series Microsoft Dynamics GP “12” Web Client Architecture. Some images and content reproduced with express permission from Microsoft Business Solutions, a division of Microsoft Corporation.


In past weeks I mentioned expanding a bit more on the Web Client to be introduced with codename GP “12”.

Web Client Overview

The Web Client is the full GP application delivered through the Web. The key pieces to be delivered will be the core application components, ISV dictionaries, and in-house customizations – Dexterity customizations. At the core of the web client is the UI update which will feature new homepage tiles, ribbons and tabs. Microsoft expects that UI performance will rival that of Terminal Server or better.

Client/Server Architecture Transition

Historically, the Microsoft Dynamics GP application has followed a 2-tier client/server architecture, which divides the application functions into two distinct, but very interrelated components: the database server and the client application.

The database server, which relies on Microsoft SQL Server, hosts the system and company data, along with extended business logic that allows it to process some of the heavier operations that would be extremely time consuming to perform at the client, for example, transaction posting business logic.

In turn, the Microsoft Dynamics GP client application, built on Microsoft Dexterity, has always performed the functions of delivering the user interface, providing data entry validation, and rendering reports – ok, so it does a bit more at times, but in context these are the key functions.

Transition from current Client/Server architecture to the Web Client architecture

A Microsoft Dexterity application is divided into two distinct elements: 1) a Runtime Engine that deals with the technology aspects of the application environment, like communicating to the operating system and establishing and managing the connection to the databases, and 2) a dictionary which hosts all the core application components and business logic, such as the forms, reports, and the sanScript code that makes the entire user interface and reports do something in response to user commands and input.

This architecture has been time tested and has served its purpose even after numerous technology changes over the years. In fact, application users have seen no disruption to the application functionality due to technology changes. The same could be said for changes in functionality- see Microsoft Dynamics GP Architectural Foundation Series with Tim Brookins for a primer on GP’s architecture.

The Web Client, built on Microsoft Silverlight delivers a set of components and services oriented toward the UI and user interaction, including user input, lightweight UI controls for use in Web applications (some other Silverlight features that probably won’t be a part of the Web Client include media playback, digital rights management, data binding, and presentation features, including vector graphics, text, animation, and images). Also Silverlight includes the Extensible Application Markup Language (XAML) for specifying layout which is heavily used by the Web Client.

The Silverlight Web Client application uses a subset of the .NET Framework that contains components and libraries, including data integration, extensible Windows controls, networking, base class libraries, garbage collection, and the common language runtime (CLR). The development language of choice, of course, is C#.

Some parts of the .NET Framework for Silverlight are deployed with the Web Client application. These “Silverlight Libraries” are assemblies not included in the Silverlight runtime and are instead shipped in the Silverlight SDK. The Silverlight Libraries used by the Web Client, are packaged up with the application and downloaded to the browser from the Server. These include new UI controls, XLINQ, Syndication (RSS/Atom), XML serialization, and the dynamic language runtime (DLR). Perhaps, not all these elements will make it to the initial release of the Web Client, but will gradually make their way in the future.

For more on Silverlight architecture click here.

Tomorrow, I will cover in more detail some of the changes required in the current architecture (from a technology stand point) to be able to serve up the Silverlight UI.

Until next post!

MG.-
Mariano Gomez, MVP
IntellPartners, LLC
http://www.IntellPartners.com/