Inactivity Auto Logout for Dynamics GP - part II

In part one of Inactivity Auto Logout for Dynamics GP, a Dynamics GP add-in was  developed to auto logout on inactivity of the GP client. With GP 2013R2 came some new functionally to message users. That functionally breaks the auto logout.

To read about the user messaging see the post, Check for User Messages(1) Dynamics GP Process Monitor

From that post you learn that there is a new timer in GP that fires approximately every minute. Setting a DEX logging on an idle GP session reveals the following:

15:27:06 B:'CheckForUserMessages of form sySendMessage', 00/00/0000 00:00:00 
15:27:06 B: 'DisplayAndDeleteUserMessage of form sySendMessage'
15:27:06 'SQLPath', 0, 7, 0, ""
15:28:21 B:'CheckForUserMessages of form sySendMessage', 00/00/0000 00:00:00
15:28:21 B: 'DisplayAndDeleteUserMessage of form sySendMessage'
15:28:21 'SQLPath', 0, 7, 0, ""
15:29:36 B:'CheckForUserMessages of form sySendMessage', 00/00/0000 00:00:00
15:29:36 B: 'DisplayAndDeleteUserMessage of form sySendMessage'
15:29:36 'SQLPath', 0, 7, 0, ""
15:30:14 B:'CheckForUserMessages of form sySendMessage', 00/00/0000 00:00:00
15:30:14 B: 'DisplayAndDeleteUserMessage of form sySendMessage'
15:30:14 'SQLPath', 0, 7, 0, ""
15:31:29 B:'CheckForUserMessages of form sySendMessage', 00/00/0000 00:00:00
15:31:29 B: 'DisplayAndDeleteUserMessage of form sySendMessage'
15:31:29 'SQLPath', 0, 7, 0, ""
15:32:06 B:'CheckForUserMessages of form sySendMessage', 00/00/0000 00:00:00
15:32:06 B: 'DisplayAndDeleteUserMessage of form sySendMessage'
15:32:06 'SQLPath', 0, 7, 0, ""
15:33:21 B:'CheckForUserMessages of form sySendMessage', 00/00/0000 00:00:00
15:33:21 B: 'DisplayAndDeleteUserMessage of form sySendMessage'
15:33:21 'SQLPath', 0, 7, 0, ""

For those interested, SQLPath parameters are:  dict_id, table_series, table_group, data_path, where 7 is for System table.

The problem in terms of our idle detection is that one of the events that resets the idle timer is the SQL path function

AddHandler DynamicsGP.Procedures.SqlPath.InvokeAfterOriginal, 
AddressOf oGlobalProcedures.DynamicsProceduresSqlPathInvokeAfterOriginal

hence GP 2013R2 is never idle due to this timer using the SQLPath function every minute.

After exchanging emails with David Brown at Rock Solid he solved the problem with the following code. He sets a flag and resets it to detect if the SQLPath execution is from the timer event or user activity. Here is his solution:

Public Sub DisplayAndDeleteUserMessageProcedureInvokeAfterOriginal(sender As Object, _
e As Applications.DynamicsDictionary.SySendMessageForm.DisplayAndDeleteUserMessageProcedure.InvokeEventArgs)
Try
checkUserMessagesEventFired = True
Catch ex As Exception
'Throw New RSTAppException(Me.GetType.Name, GetCurrentMethod.Name, ex, , False)
End Try
End Sub

Public Sub DynamicsProceduresSqlPathInvokeAfterOriginal(sender As Object, _
e As Applications.DynamicsDictionary.SqlPathProcedure.InvokeEventArgs)
Try
If Not checkUserMessagesEventFired Then
oInactivityTimer.Tick()
End If
checkUserMessagesEventFired = False
Catch ex As Exception
'Throw New RSTAppException(Me.GetType.Name, GetCurrentMethod.Name, ex, , False)
End Try
End Sub

Hence we again have the ability to implement the auto logout function, thanks David!

dexLabelProvider & LinkField explained

image

The dexLabelProvider is a component that implements IExtenderProvider, thus adding an extra property (LinkField) to label components dropped onto a DexUI form or forms that inherit from it. The provider is used by the DexUI form’s onPaint to draw a line between label (or linklabel) and control defined in the LinkField property.

In more detail

Add a DexUI form to your add-in project or inherit form a dexUI form and in the tray is found a dexLabelProvider.

image

The dexLabelProvider keeps track of the labels on the form that are linked visually to text boxes, and thus should have a line connecting them on the User Interface in order to match into the “visual feel” of GP. In the screenshot below you can see the label and text box, both selected in Visual Studio, see a line joins them, a line drawn by the form paint. That it should be drawn is held by the label provider as a hash table of controls to link in this way.

image

The dexLabelProvider implements the IExtenderProvider that allows components to add their own properties to other components in the Visual Studio UI designer. In the case of dexLabelProvider, it adds the following decoration to the DexLabelProvider, so as to impose a LinkField property to other components on the form.

[ProvideProperty("LinkField", typeof(Label))]

However the other method to implement the IExtenderProvider is the CanExtend method. In the case of dexLabelProvider it is set to return true only if the object is Label, hence it will only add the property to controls of type label.

image

The class is very simple, holding a HashTable  of controls it is extending (i.e. controls it is adding visual link lines to).

DexUIForm creates an instance of dexLabelProvider to keep track of the extended labels.

In passing it is worth mentioning that DexUIForm checks to see if that component is a LinkLabel or Label type, if so it sets that control’s AutoSize to false, this is why whenever you set AutoSize to true, it reverts to false.

The OnPaint of DexUIForm does the business of drawing the line. Each control is checked to see if it is a label or linklabel type, if it is, then it asks the label provider to supply the control that links to this label (if any). It does this by looking up in the hash label the name of the linked control, using the current controls name as key. It then returns that control from the form control collection (usually a text box or similar). “promptLink” represents the linked control in the code snip below.

In the snippets below we can see that depending on the relative position of link label and control it links to, two points are derived, between which a line is drawn, the link we see in the UI linking the two controls.

if (promptLink != null && e.ClipRectangle.IntersectsWith(this.GetControlRectangle(control as Label, promptLink)))
{
Point empty = Point.Empty;
Point empty2 = Point.Empty;
if (control.Bounds.Left < promptLink.Bounds.Left)
{
empty2 = new Point(control.Bounds.Left - 3, control.Bounds.Bottom + 2);
empty = new Point(promptLink.Bounds.Left, control.Bounds.Bottom + 2);
}
else if (control.Bounds.Right > promptLink.Bounds.Right + 3)
{
empty2 = new Point(control.Bounds.Right + 3, control.Bounds.Bottom + 2);
empty = new Point(promptLink.Bounds.Right, control.Bounds.Bottom + 2);
}
if (empty2 != Point.Empty)
{
e.Graphics.DrawLine(new Pen(ColorHelper.Instance.GetFieldBorderColor()), empty2, empty);
}
}

private Rectangle GetControlRectangle(Label control, Control link)
{
if (control.Bounds.Left < link.Bounds.Left - 3)
{
return new Rectangle(control.Bounds.Left - 3, control.Bounds.Bottom + 2, link.Bounds.Left - control.Bounds.Left + 3, 1);
}
if (control.Bounds.Right > link.Bounds.Right + 3)
{
return new Rectangle(control.Bounds.X - 3, control.Bounds.Bottom + 2, control.Bounds.Right - link.Bounds.Right + 3, 1);
}
return new Rectangle(0, 0, 0, 0);
}

If the label is to left of the control, the line is from the point at the bottom left corner of the label to the bottom left of the control it links to. If the label is to the right of the control, the line goes from the right hand bottom corner to the right hand bottom corner of the linked control. Notice too, that no account of the vertical position is taken, it is up to the developer to position the controls such that the line intersects correctly in a vertical axis.

A simple implementation that gives Dynamics GP Visual Studio Tools developers the ability to have native feeling forms.

Dynamics GP Power Tools–what will it not do?

image

If you are developing on top of Dynamics GP, or perhaps go to the many Dynamics GP conferences, or maybe just using search engines to find answers to your common GP problems, then you will have encountered David Musgrave (MVP).

His work is pervasive in the Dynamics GP world and he has saved my bacon, more times than I can count via technical blogs revealing the obscure corners of the GP product that I too often find myself despairing in.

Until a year ago David was working for Microsoft. You may have experienced that there are major world news events that you remember exactly where and when you heard that big news. I remember the moment I was told by a MS developer that David was having to leave Microsoft, news that made the group groan. I had been waxing lyrical about his work and suddenly felt deflated. Not long after, that same news shook the partner community as it propagated out to all corners of the world. You may ask, Why the drama? Well David has given a lot to the GP community both user and partner side of it and he is someone that I think we all respect and hold in highest regard and esteem. I also think that we were being a bit selfish in worrying that this news might herald his exit from that community. Thankfully this was not the case! In fact it turns out that it may have been one of the best things that could have happened for us and time will tell for David. For now all us GP developers have our code warrior, bridging the chasm that lies between Dexterity, the barren dry scripting language GP is written in and the world of .NET development, the lush palace where the rest of us live (yes I mean palace)..

A year ago, the dust settled, David went quiet for a little while and surfaced with a product, Power Tools published by his company Winthrop Development Consultants, whose logo has an uncanny resemblance to GP Dynamics sails log (although it predates his MS days). David has released the product and is continuously developing it a high rate of knots. It is a product that helps the rest of us developers be more productive, and in many cases enables us access to do things with some aspects of GP that otherwise we would be barred from! The product is called GP Power Tools, for indeed it is powerful. The product provides not only developer APIs and helpers to develop solutions with Dynamics GP, it also provides facilities for administrators to perform admin tasks and access to specialised debugging diagnostic tools together with exposing so many GP configuration switches. Power Tools has sprung from a product from Microsoft named The Support Debugging Tool, something that David actually wrote in the first place and got the rights back from Microsoft for.

Features

Find below the extensive feature list, as of today Build 20, from the user guide: GP Power Tools User Guide

Feature

Description

Manual Logging Mode

Manually turn on SQL Logging and Dexterity Logging and Profiling

Individual Logging

Control Individually control SQL Logging and Dexterity Logging and Profiling

Dex.ini Settings

Change System and Debugger Dex.ini Settings

Resource Information

Obtain Details of any Table, Form, Window, Field or Report resource

Security Profiler

Monitor all Security check activity

Security Information

Display Security settings for specific resources for a user and company

Security Log

Security activity tracking for users, companies and the entire system.

ScreenShot

Capture and either email or save Screenshots and System Status information

Send Email

Send Email messages from within the application.

Automatic Debugger Mode

Automatically starts logging and watches for specified events

Dictionary Control

Enable and Disable third party products

XML Table Export

Export any table(s) to an XML file

XML Table Import

Import previously exported tables

Runtime Execute

Run Dexterity sanScript scripts

SQL Execute

Run Transact SQL scripts

.Net Execute

Run C# and VB.Net scripts

Configuration Export/Import

Export and Import settings

Configuration Maintenance

Clear Debugging Tool settings

Administrator Settings

Change system wide Administrator Settings controlling the behavior of the tool

Dex.ini Configuration

Automatically update Dex.ini settings across multiple workstations.

Database Validation

Validate SQL user and database information and table structures.

About GP Power Tools

Display version and build information or un-install GP Power Tools

 

Tools & Utils for all

toolboxPower tools has some very dangerous, in an exciting way and powerful facilities that only power users, developers or system administrators should use and offers other features that are end user friendly. End user features such as emailing a screenshot & snapshot of the Dynamics GP configuration to the support people in your organisation on the press of a button in GP is really useful.

Indeed Power Tools is much like one of those concertina tool boxes, where you can dig deeper and deeper inside to find just the right fitting tool.

One more thing, David has a sponge like special power, he soaks up any ideas in the atmosphere from users, partners and I can only guess where else. He then refines those ideas into feature sets for products. His pace of development is astounding, so I have no doubt that by this time next year there will be little Power Tools can not do! I am also expecting to see some other products emerging into the GP market, long may it last.

Now, go read the product pages, get it ordered and start benefiting from David’s hard work.