我有一个遗留的 Delphi6 应用程序。 它利用了 iManage 的 COM 接口 DLL。 (作为 _TLB 单元文件导入到 D6 中,您可以将其包含在使用语句中)但是... iManage 已终止其 COM Api。 iManage Work 的 API 现在是 REST-Api。
iManage 发布了专为 .NET 应用程序制作的 iManage Work SDK 及其 iwhostTestApp 示例应用程序,该应用程序使用: iwto.dll、iwhost.dll、IWInterfaces.dll 及其 iwSessionCache.exe (这可以在用户创建并成功验证会话后保持可缓存会话打开。)
我希望我能做的,可能是在 C# 中创建一个 C# 类型库,其中包含方法调用,反过来,它可以调用上述 iManage 库中包含的各种方法调用和类。 .然后是我的“外包装”DLL,可能会利用 RGeisecke 的 UnmanagedExports 1.2.7 NuGet 包?可能会将值返回到 Delphi6 应用程序。
目前,我的 D6 应用程序正在对我编写的 C# 中间应用程序(利用其 SDK)进行 ShellExecute,然后使用 iManage 提供的 dll 并按照 iwhostTestApp 项目中的示例编码,调用所需的 iManage功能。并将相关信息或错误消息写回到 SQL 表记录中,然后使用 Windows Messaging,当编码命中 Application.Exit(cancelEventArg) 时调用中间应用程序的“_FormClosed”方法时,它会发送回 WindowsMessaging 消息, D6 应用程序将等待并监听。然后,D6 应用程序将采取行动,获取返回的 SQL 表记录字段内容,并从该备注字段中解析出来。要么是一个 ErrorMsg 表明出了问题,要么......它会读出返回信息的一部分,例如从 iManage 的围栏一侧发回的 MonikerStr 信息。
我还不熟悉如何在 D6 中编写(OAuth 身份验证的)REST 调用代码。
因此,我开始进行一系列 Bing Co-Pilot AI 辅助搜索,看看是否有办法从 D6 中调用 C# DLL 方法。
我发现了各种 stackoverflow 帖子 RE:利用 RGeisecke 的 UnmanagedExports NuGet 包。
目前,我只是尝试创建一个 C# 类型库,如下所示:
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;
}
}
}
并在 D6 中创建一个测试应用程序来尝试调用此方法。
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.
当我在解决方案中的 IManExecutorLib 项目上执行“构建”>“清理”,然后执行“构建”>“重建”时,并将其放入 bin\x86\Debug 中的文件复制到 et6.0-windows\ 文件夹...进入文件夹 D6 生成小测试 *.exe:
我注意到,在我添加的这个 IManExecutorLib 类库的项目属性中,我最早可以选择的目标框架是 .NET 5.0,目前选择的是 .NET 6.0。另外,VS IDE 让您为该项目设置属性的外观和感觉,看起来比此解决方案中包含的其他库项目更新/不同,前一个仅允许选择最多可达 .NET 目标框架4.8为最高。
看起来当我将这两个单独的库项目添加到此解决方案中时...我必须在此屏幕中选择不同的选项来将这个新项目(IManExecutorLib)添加到当前解决方案中。
所以,首先:我想做的事情可能吗?制作一个可以在 D6 中调用方法的 C# DLL? (这里希望在 DLL 中创建方法,这可能能够调用 iManage Work 的较新 SDK 的方法)以某种方式利用 RGeisecke 的 UnmanagedExports NuGet 包?
如果是这样...我是否需要确保此解决方案中包含的所有其他项目(即使与此项目没有特别相关)也设置为这种较新的类型,让我选择 .NET 5.0 及更高版本?
我最终在 Visual Studio 中需要删除而不是重做我想要使用 UnmanagedExports 的新 DLL 项目。
我必须选择“类库(.NET框架)”(而不是“类库”)。因此,它适用于 .NET v4.8 及更低版本的类库,而不是 .NET 5.0 及更高版本。这似乎是这项工作的关键部分。
另外..你必须将方法调用定义为静态。
不管它是针对谁的,我都包含了太多的信息。好吧,当您不熟悉新事物时……想法是,如果您在原始帖子/问题中提供了所有潜在的相关细节,那么那些可能对您有帮助的人就不会提出所有这些来回的问题,因为您预先提供了所有详细信息。
当向第三方开发支持询问问题时,我经常必须通过这种方式向他们发送电子邮件。它大大节省了来回电子邮件的时间。