How to Execute a Dexterity Procedure Programmatically

0

How can I execute a Dexterity procedure programmatically?

Goal:

I want to reset a user password within Great Plains 2018 programmatically. For our purposes, programmatically does NOT refer to the following:

  • Clicking buttons in a user interface manually, particularly after launching Dynamics.exe
  • Running a Great Plains 2018 macro

Background:

  • The only possible supported solution for what I am trying to achieve I believe must rely on Dexterity. I have no idea how to execute a Dexterity procedure programmatically, so this might be impossible.
  • I have a Dexterity script (Dynamics procedure) defined which is very simple—it resets a GP user password via Login_AlterLogin(). It has no parameters and is based on the examples provided in Dex.chm help file.
  • To deploy and use this Dexterity script I have done the following:

    1. Created a dictionary (dev.dic)
    2. Created and compiled the Dexterity script within my editable dictionary (dev.dic)
    3. Created a CNK file (dev.cnk)
    4. Launched GP and performed unchunking
    5. Generated a DLL using Dag.exe (Application.Dev.dll)
    6. Added the assembly into my Visual Studio project (Application.Dev assembly added to a C# console app)
    7. Attempted to Invoke() the procedure (Dexterity.Applications.Dev.Procedures.Dev.Invoke();).
  • My C# app attempts to make a GPConnection before invoking the procedure, as shown below. I have validated that my GPConnection is successfully connecting (gpConn.ReturnCode = 1).

Code (Dexterity):

This is an example Dexterity script taken from the Dex.chm help file:

"The following example shows how a SQL administrator can set the password for a specific login. In this case, the password for the login “STEVE” is changed to “GreenRoutine5”."

local integer status;
local long retcode;
local long login_options;

{Retrieve the existing login options}
status = Login_GetLoginSettings("STEVE", login_options); 

status = Login_AlterLogin("RST", "STEVE", login_options, retcode, "GreenRoutine5");

case status
in [STATUS_SUCCESS]
    warning "Login successfully updated.";
in [STATUS_MEMORY_ERROR]
    warning "Memory error.";
in [STATUS_LOGIN_FAILED]
    warning "Login failed.";
in [STATUS_TOO_MANY_CONNECTIONS]
    warning "Too many connections.";
in [STATUS_DATASOURCE_REJ]
    warning "Datasource rejection.";
in [STATUS_UNABLE_TO_CONNECT]
    warning "Unable to connect.";
in [STATUS_LOGIN_INVALID]
    warning "Login invalid.";
in [STATUS_INVALID_PERMISSIONS]
    warning "Invalid permissions.";
in [STATUS_NOT_LOGGED_IN]
    warning "Not logged in.";
in [STATUS_LOGIN_PASSWORD_SIMPLE]
    warning "Password is too simple.";
in [STATUS_LOGIN_PASSWORD_SHORT]
    warning "Password is too short.";
in [STATUS_LOGIN_PASSWORD_LONG]
    warning "Password is too long.";
in [STATUS_LOGIN_PASSWORD_HISTORY]
    warning "Password violates password history.";
end case;

Code (C#):

using Microsoft.Dexterity;
using System.Data.SqlClient;

class Program {
    static void Main(string[] args) {
        SqlConnection sqlConn = new SqlConnection();
        sqlConn.ConnectionString = "Data Source=DEV1;Initial Catalog=RST;";

        int resp = GPConnection.Startup();
        GPConnection gpConn = new GPConnection();
        gpConn.Init("CompanyName", "1234_special_keys_for_vstools_5678");
        gpConn.Connect(sqlConn, "DEV1", "sa", "Secret_pwd678");

        Microsoft.Dexterity.Applications.Dev.Procedures.Dev.Invoke(); //exc thrown here
        resp = GPConnection.Shutdown();
    }
}

Error:

System.TypeInitializationException HResult=0x80131534 Message=The type initializer for 'Microsoft.Dexterity.Applications.root' threw an exception. Source=Application.Dev StackTrace: at Microsoft.Dexterity.Applications.DevDictionary.DevProcedure.get_WrappedScript() at Microsoft.Dexterity.Applications.DevDictionary.DevProcedure.Invoke()
at Program.Main(String[] args) in C:\Users\administrator.ROCKSOLID\source\repos\gp_test\gp_test\Program.cs:line 14

Inner Exception 1: NullReferenceException: Object reference not set to an instance of an object.

StackTrace " at Microsoft.Dexterity.Bridge.AppDispatchProxy.get_LaunchFileName()\r\n
at Microsoft.Dexterity.Bridge.DictionaryRoot..ctor(Int32 productId, Boolean isFormsDictionary)\r\n at Microsoft.Dexterity.Applications.root..cctor()" string

c#
dynamics-gp
asked on Stack Overflow Oct 2, 2019 by nairware • edited Oct 3, 2019 by nairware

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0