1st Saleslogix .NET Extension
Posted By: nicocrm on September 17th, 2008 in Saleslogix
No Gravatar

Technically not the very first one as I have played with it before but this is the first case where it actually allows me to do something that would have been impossible without it.

One very useful resource was this page on SlxDeveloper: http://www.slxdeveloper.com/page.aspx?id=56.  All articles are very interesting but this one in particular is full of example and extremely useful.  Thanks so much to Ryan for putting this together.

The extension in question is relatively simple, it builds a logo dynamically and displays a preview in the client.  As there is no way to manipulate graphics in VBScript without the .NET extensions this would have required an external program or a custom COM component and distributing that to the remotes could have been a real hassle.

There were a few things to note although the explanations on the afore-mentioned articles were so good that I won’t repeat them here:

  • The .NET extension has to be compiled against the exact same version of Saleslogix that is going to be used on the client.  This implies that it will have to be relinked after an upgrade.  Otherwise, you won’t get a clear error message, but the call to Application.Managed.Run will fail.
  • The Saleslogix assemblies (Sage.SalesLogix.NetExtensions.Framework.dll and Sage.SalesLogix.NetExtensions.Core.dll) have to be registered in the GAC.  If they aren’t, you have to add them (either use gacutil, or simply drag/drop them to C:\Windows\Assembly in the explorer).  Normally this is done by the installer but apparently this sometimes fail.
  • The .NET extension manager does not run on 64bit OS.  So you have to register the extensions on a separate machine.
  • The .NET extension bundles are not terribly reliable… I think you are better off just registering them by hand on the production machine.
  • This is the code that I use to load my custom control and have it build and display the logo:
    handle = Application.Managed.Create("Barrel Logo Extension", _
        "SSSWorld.BarrelLogoExtension.SlxLoader")

    On Error Resume Next
    Set logo = Application.Managed.Run(handle, panLogoContainer.HWND)
    If Err.Number <> 0 Then
        MsgBox "Error loading logo control: " & Err.Description & vbCrLf & _
            "Please verify that you have the current Saleslogix service pack (v7.0.1)." & vbCrLf & _
            "If this error persists, please contact your Administrator.", _
            vbCritical, "Error"
        ModalResult = mrCancel
        Exit Sub
    End If
    logo.LoadBarrelLogo g_sFileName, g_sLine1, g_sLine2, g_sLine3, g_sLine4, g_sLine5

The “BaseRunnable” implementation (called SlxLoader) returns a ComVisible object that can then be manipulated by the VBScript.  First I tried having it return the UserControl directly but this would not go through (presumably COM did not know how to control it).  However you do not have to register the COM interface using regasm or the “Register for COM interop” checkbox – just having the type bear the ComVisible attribute is enough.  And the object in question holds a reference to the UserControl – this is the implementation of the LoadBarrelLogo method:

public void LoadBarrelLogo(String imgPath, String line1, String line2, String line3, String line4, String line5)
{
  _logo.LoadBarrelLogo(imgPath, line1, line2, line3, line4, line5);

}

and the Run method:

public override object Run(object[] args)
{
    if (args.Length != 1 || !(args[0] is Int32))
        throw new InvalidOperationException("Usage: SlxLoader.Run(hwnd)");

    IntPtr formHwnd = new IntPtr((int)args[0]);
    _logo = new BarrelLogo();
    Win32Util.SetParent(_logo.Handle, formHwnd);
    SSSWorld.Common.Win32Util.RECT formSize;
    if (Win32Util.GetWindowRect(formHwnd, out formSize))
    {
        _logo.Size = formSize.Size;
    }
    return this;
}

This code is explained in detail in the SlxDeveloper article.

These .NET extensions are a very nice tool to have.  There is definitely some room for improvement in the implementation, though sadly as the focus has shifted away from the network client it is unlikely that we will see any.  In most cases if it is possible to do it in VBScript instead it will be easier to manage in the long term.  But having the possibility to do more if absolutely needed is good.