How can I call upon C# DLL methods from within a Delphi6 application using RGiesecke’s UnmanagedExports NuGet package?

I have a legacy Delphi6 app.
It was making use of iManage’s COM interface DLL’s. (Imported into D6 as _TLB unit files you’d include in the uses statements) BUT… iManage has End-of-Life’d their COM Api.
iManage Work’s API is now a REST-Api.

iManage released an iManage Work SDK, made for .NET apps along with their iwhostTestApp sample application, which makes use of:
iwto.dll, iwhost.dll, IWInterfaces.dll, and their iwSessionCache.exe
(which can keep cacheable sessions open after the user has created and successfully authenticated a session.)

What I was hoping I could do, is possibly in C# create a C# Type Library, with method calls within it, which could, in-turn, call upon various method calls and classes contained within the iManage libraries mentioned above… and then my “outer-wrapping” DLL, potentially making use of RGeisecke’s UnmanagedExports 1.2.7 NuGet package perhaps?, to possibly return values back to the Delphi6 app.

Currently, my D6 app is ShellExecute’ing a C# intermediary app I wrote (making use of their SDK) which would then turn-around, using iManage’s provided dll’s and going by the sample coding in iwhostTestApp project, would call upon the desired iManage functionality. And write pertinent information or error messages back into an SQL table record, then using Windows Messaging, when the intermediary app’s “_FormClosed” method was called when the coding hits Application.Exit(cancelEventArg) it’d send a WindowsMessaging message back, that the D6 app would be waiting and listening for. The D6 app would then act, and fetch the returned SQL table records field contents it’d parse out of this memo field. Either an ErrorMsg indicating something went wrong, or.. it would read-out piece-parts of the returned information such as the MonikerStr info sent back from iManage’s side-of-the-fence.

I am not yet familiar with how to code for (OAuth authenticated) REST calls in D6.

So I began doing a bunch of Bing Co-Pilot AI-assisted searches to see if there’s a way to call upon a C# DLL method from within D6.

I found various stackoverflow posts RE: making use of RGeisecke’s UnmanagedExports NuGet package.

For now, I’m just trying to create a C# Type Library as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using RGiesecke.DllExport;

namespace iManExecutorLib
{
    public partial class IManExecutorLib
    {

        public IManExecutorLib()
        {
        }

        [DllExport]
        public static void iManV2SDKCall(
            [MarshalAs(UnmanagedType.LPWStr)] string cmdLineParms,
            [MarshalAs(UnmanagedType.LPWStr)] out string sReturned)
        {
            var sRslt = string.Empty;

            sRslt = "cmdLineParms passed-in = <" + cmdLineParms + ">";

            sReturned = sRslt;
        }
    }
}

And making a Test app in D6 to attempt calling this method.

unit MainForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TfrmMain = class(TForm)
    mmoLog: TMemo;
    btnGo: TButton;
    procedure btnGoClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure WriteLog(sMsg : String);
  end;

var
  frmMain: TfrmMain;

const
  kDLLname="iManExecutorLib.dll";

procedure iManV2SDKCall(cmdLineParms: PWideChar; var sReturn: PWideChar); stdcall; external kDLLname;


implementation

{$R *.dfm}
procedure TfrmMain.WriteLog(sMsg : String);
begin
  mmoLog.Lines.Add(sMsg);
  mmoLog.Refresh;
end;

procedure TfrmMain.btnGoClick(Sender: TObject);
var wsCmdLineParms  : WideString;
    wsReturned      : WideString;
    pszCmdLineParms : PWideChar;
    pszReturned     : PWideChar;
begin
  wsCmdLineParms   := 'Here are some cmdLineParms.';
  pszCmdLineParms  := PWideChar(wsCmdLineParms);
  self.WriteLog('wsCmdLineParms=<'+ wsCmdLineParms + '>');

  ////////////////////////////////////////////
  iManV2SDKCall(pszCmdLineParms, pszReturned);
  ////////////////////////////////////////////

  wsReturned := WideString(pszReturned);

  self.WriteLog('wsReturned=<' + wsReturned + '>');
end;

end.

When I do a Build>Clean, Then a Build>Rebuild on the IManExecutorLib project within the Solution, and copy the files it puts into the bin\x86\Debug\net6.0-windows\ folder… over into the folder D6 generates the little test *.exe in:
List of files generated by the C# Type Library project

When I attempt to run the D6 Test App, I get the following error:
Application Error

I’ve noticed that in the Project Properties for this IManExecutorLib Class Library I added, the earliest Target Framework I could choose was .NET 5.0, it’s currently selected at .NET 6.0. Also the look-and-feel of how VS IDE let’s you set properties for that project, looks newer/different than the other library Project that was contained in this solution, that prior one only allows choosing a .NET Target Framework of only up to 4.8 as the highest.

Looks like when I added these two separate library projects into this Solution… I must have picked a different choice in this screen for Add’ing this newer Project (IManExecutorLib) to the current Solution.
Shows the two different Class Library Project types which are subtly different

So, first: Is what I want to do possible? Make a C# DLL that I can call methods of from w/in D6? (The hope here, to make methods in a DLL, which might be able to call into methods of iManage Work’s newer SDK) Making use of RGeisecke’s UnmanagedExports NuGet package somehow?

And if so… would I need to make sure that all the other Projects contained in this Solution (even though not specifically related to this Project) are also set to this newer type that let’s me pick .NET 5.0 and higher?

  • 2

    This is a very long post with a lot of completely irrelevant information and back history. StackOverflow is a Q&A site for specific coding questions. Keep it short and simple.

    – 

  • UnmanagedExports and Type Libraries are nothing to do with each other. UnmanagedExports is used to make a C style DLL export function. Type libraries use COM classes.

    – 

Leave a Comment