Friday, August 30, 2013

Microsoft Dynamics GP 2013 Service Pack 2 is now available

Service Pack 2 for Microsoft Dynamics GP 2013 is now available for your consumption. Microsoft has released the product ahead of schedule - originally, September of 2013. I guess this will make for an even more exciting Microsoft Dynamics GP Technical Airlift 2013.
Service Pack 2 is probably the most comprehensive update so far to Microsoft Dynamics GP 2013 and includes a number of fixes and enhancements. Let's take a quick look:
Modules activated for Web Client:
  • Field Service
    • Service Call Management
    • Depot Management
    • Preventative Maintenance
  • Project Accounting
  • Manufacturing
    • Bill of Materials
    • Manufacturing Order Processing
    • Master Production Scheduling
    • MRP
    • Manufacturing Suite
  • Fixed Assets Enhancements
  • Business Activity Statement (BAS) for Australian GST
  • Payment Document Management (PDM)
Features Exclusive to Web Client:
  • Visual Studio Tools for Web Client v1.0
  • Keyboard Shortcut enhancements
  • Change single machine configuration to support both the Web Client web site and runtime service using the same port  
  • Add styling to ribbon to show focus  
  • Web client messaging retry/refresh & Client Side error handling / notification improvements
  • Better scrollbars for standard reports 
New Desktop & Web Client Features:
  • GL - Roll down changes to Account Segment Description
  • Reconcile checkbook without marking transactions
  • Cash Receipts Inquiry display checkbook ID
  • Customer Combiner & Modifier
  • Vendor Combiner & Modifier
  • Payables Void Enhancements
  • AA Finance Charge assessment
  • AA and Sales order deposits
  • Payroll Inquiry Check Date Sort Options
  • Applicant E-mail in HR
  • Doc Attach 2.0:
    • Document Flow
    • Status Tracking
    • Delete Password
    • Attachment Properties
    • Attachment Email
    • Delete Utility
  • SmartList Splitter
  • SmartList Designer
Note: the SmartList Splitter was a cool piece of code made available with the Support Debugging Tool initially. If you are running Microsoft Dynamics GP 2010, you can take advantage of this via the Support Debugging Tool.
Service Pack 2 can be recognized by its new build number, 12.00.1482 and the Dexterity version is 12.00.0269. For more version details download the MDGP2013_MSPVersionList.xls file. For the install guide and a list of issues fixed, download the 12.0SP2_install_guide_ENUS.pdf file. Both files are available from the main Service Pack page (or from the links here).
Service pack 2 is available from the Service Pack 2 page or you can download the full updated DVD image:

Product Release Downloads for Microsoft Dynamics GP 2013 Secure Link
Service Pack, Hotfix, and Compliance Update Patch Releases for Microsoft Dynamics GP 2013 Secure Link

Product Release Downloads for Microsoft Dynamics GP 2013 Secure Link
Service Pack, Hotfix, and Compliance Update Patch Releases for Microsoft Dynamics GP 2013 Secure Link

The Microsoft Dynamics GP Support and Services Blog has more information related to Service Pack 2. Please visit their page for more information:

Until next post!

Mariano Gomez, MVP
IntellPartners, LLC

Monday, August 26, 2013

Accessing Microsoft Dynamics GP Default Settings from Visual Studio Tools

Rarely you will hear the Dex.ini file being called the Microsoft Dynamics GP defaults file. However, the Dex.ini contains keys (and their associated values) that define how Microsoft Dynamics GP behaves in some cases. For example, SQLLastUser=sa stores the login of the last user who accessed the system on that specific instance of Microsoft Dynamics GP, in this case, 'sa'. Likewise, AutoInstallChunks=TRUE, allows Microsoft Dynamics GP to bypass prompting the user for new code (chunk file) to be installed at the time of launching the application. There are other settings controlling how certain features behave.

You can find a list of Dex.ini settings here.

Recently, I was helping a good friend of mine up in Maine who attended my Dexterity class in Boston and this time he wanted to know how to read the path for the Microsoft Dynamics GP help file. Of course, there's a simple (predefined) method for this as my good friend Patrick Roth with the Escalation Engineering team in Fargo pointed out, if you are familiar with some of Microsoft Dynamics GP form procedures:

string strPath = "";
strPath = Dynamics.Forms.MainMenu.Functions.GetDynamicsHelpPath.Invoke();

So, let's assume you had no clue this function existed. How would you address this issue? Frankly, I can think of at least 3 ways to do this:

1) Using a hybrid method whereby you create a Dexterity dictionary to wrap the Defaults_Read() Dexterity sanScript function into a user-defined global function. This method presents a challenge as you need to use the Dictionary Assembly Generator (DAG.EXE) to create an assembly you can reference from your VST project. In addition, you may or may not want to add an entirely new dictionary into the picture, when delivering your final solution. However, in case you are interested, this is the implementation:

GetDexIniSetting function

For more information on developing hybrid applications with Dexterity and Visual Studio Tools take a look at my articles:

Developing Microsoft Dynamics GP hybrid integrating applications
Hybrid development for the Managed Code developer
Hybrid development for the Managed Code developer (cont.)

2) You could use the Continuum API from Visual Studio Tools to access the Defaults_Read() sanScript function. The Continuum API is the Component Object Model (COM) API that is available for Microsoft Dynamics GP. The Continuum API documentation is available for download here. In this method, all you have to do is add a reference to the interop.Dynamics.dll COM library, which hosts the Continuum API.

// Created by Mariano Gomez, MVP
// This code is licensed under the Creative Commons 
// Attribution-NonCommercial-ShareAlike 3.0 Unported License.

public string GetDexIniSetting(string searchKey)
   ParameterHandlerClass myParamHandler = new ParameterHandlerClass();
   { Dynamics.Application gpApp = (Dynamics.Application)Activator.CreateInstance(Type.GetTypeFromProgID("Dynamics.Application"));
     if (gpApp == null) 
       return "";
       string passthrough_code = "";
       string compile_err;
       int error_code, result;

       result = gpApp.SetParamHandler(myParamHandler);
       myParamHandler.IN_Key = searchKey;

       passthrough_code += "local boolean err_val;";
       passthrough_code += "local string dex_key_val, dex_key;";
       passthrough_code += @"err_val = OLE_GetProperty(""IN_Key"", dex_key); "; 
       passthrough_code += "dex_key_val = Defaults_Read(dex_key);";
       passthrough_code += @"err_val = OLE_SetProperty(""OUT_KeyVal"", dex_key_val);";

       gpApp.CurrentProductID = 0; 

       error_code = gpApp.ExecuteSanscript(passthrough_code, out compile_err);
       return myParamHandler.OUT_KeyVal;
   { MessageBox.Show("Failed to initialize gpApp");
     return "";

public class ParameterHandlerClass
  public string IN_Key { get; set; }
  public string OUT_KeyVal { get; set; }

In the above code, we define a parameter handler class with couple properties for the key that will be read from the Dex.ini and the key value to be retrieved.

In our GetDexIniSettings method, we instantiate our class and use the Continuum SetParaHandler() method to load the IN_Key property value. We then setup our pass-through code and invoke sanScript's OLE_GetProperty() function to retrieve the value of the IN_Key from our VST application via some old fashioned OLE automation. The OLE_SetProperty() function then returns the value to our class property, OUT_KeyVal.

That's it!

3) The third method uses some classic C# reflection to get the path of the AddIns. It then converts this to the path of the Data folder and the dex.ini file, and then uses the Pinvoke() method to read the key in the dex.ini and return the value.

[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
 static extern uint GetPrivateProfileString(
 string lpAppName,
 string lpKeyName,
 string lpDefault,
 StringBuilder lpReturnedString,
 uint nSize,
 string lpFileName);

//get path which should be the addins folder
String strPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

//look for \Addins path
if (strPath.EndsWith(@"\AddIns", true, System.Globalization.CultureInfo.InvariantCulture) == true)
{ //and if we find one replace with the data folder
  strPath = strPath.Replace(@"\Addins", @"\Data\Dex.ini");
{ //if not in addins then we must be in the root GP folder (like GP 2013 does with GP addins) so tack on \Data
  strPath = strPath + @"\Data\Dex.ini";
StringBuilder sb = new StringBuilder(100);
uint res = GetPrivateProfileString("General", "Pathname", "", sb, (uint)sb.Capacity, strPath);

// Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the 
// Microsoft Public License (MS-PL,

The above method comes courtesy of my good friend Patrick Roth with the Escalation Engineering team at Microsoft.

All the above methods are generic in nature and can read more than just a specific key. It's good to know that there's more than one way to do things. If you are going all hybrid, there's a code for that! If you want to be self-contained, there's a code for that! If you want to deviate completely from sanScript because you hate it or don't know it, there's a code for that! Whatever route you choose it must work to your benefit.

As a good Australian friend of mine would say, "The right solution is the one that works!".

Until next post!

Mariano Gomez, MVP
IntellPartners, LLC

Tuesday, August 13, 2013

How to reset Business Analyzer settings

Just recently, I ran into an interesting case where the consultant had installed and configured Business Analyzer for a user. However, during the configuration process, the consultant marked all available reports for all available companies, which put Business Analyzer into a tailspin as it attempted to load all this information. The consultant proceeded to shut down the application using the Task Manager program.

When he restarted Business Analyzer, the application went back into a tailspin, displaying only the loading screen with a "Connecting to Server" message for over an hour. Fearing this would be a permanent issue due to the number of reports and companies selected, the question was just obvious: how to reset Business Analyzer configuration settings.

The boring theory

If you have downloaded Business Analyzer from the Windows Store or are still running the Business Analyzer desktop client, chances are you had to go through a setup process. In Windows 8, this involves swiping the Edge UI to obtain the charms and clicking on Settings to obtain the Configuration pane.

Business Analyzer for Windows 8 configuration

Once in the Configuration pane you are asked to enter information about the Report Server from which reports will be loaded. Once the credentials have been validated, you will be directed to add reports accordingly.

Business Analyzer Reports Configuration

Selecting all reports from all companies under a specific instance (I'm running GP 2013) can have adverse performance effects if you are in an environment with multiple companies, as Business Analyzer attempts to obtain information for each report, for each company from Report Server. The important part though is, this information is stored locally, under the user profile folder, in the hidden AppData folder, where an XML configuration file is created (user.config). Since all reports were selected for all companies, building this file would normally take a considerable amount of time.

The Solution

To fix the problem all that's needed is to remove the Business Analyzer configuration folder, which can be found under:


After this, you can re-launch Business Analyzer and go back to the configuration options where you will be prompted to enter the server information and selected the reports to display once again. Easy enough!

Until next post!

Mariano Gomez, MVP
IntellPartners, LLC