Delphi 5 可以使用 C# .Net 库吗?
Can Delphi 5 use a C# .Net Library?
我正在更新遗留 Delphi 5 应用程序(我们有代码),该应用程序通过使用用户提供的凭据进行绑定来针对 LDAP/AD 进行身份验证。但是,我们使用的库无法通过端口 636 或 3269 绑定 LDAPS (LDAP/SSL)。
我看到在 C# 中针对 LDAP/AD 进行身份验证可以像这样简单:
PrincipalContext pc = new PrincipalContext(ContextType.Domain, "testnet.testad.org:636", "dc=testnet,dc=testad,dc=org");
bool validated = pc.ValidateCredentials(username, password, ContextOptions.Negotiate);
我正在考虑将必要的调用包装在一个 .DLL 中,然后从 Delphi 应用程序中调用该调用。但是,我假设存在 'gotchas' 的雷区会阻止它变得如此简单。
使用UnmanagedExports这真的很简单。
您从功能的界面开始,如下所示:
type
IManagedInterface = interface
['{9F5A2431-5559-410C-BAB4-5144CA8C0B7B}']
function CheckCredentials(AContextName, AContainerName, AUserName,
APassword: WideString): integer; safecall;
end;
这可能不是参数类型的最佳选择,因为您不能使用 NULL
来调用用户名和密码,并且您可能希望将其他参数(如上下文类型)传递为好吧,但你明白了。
然后在 VS 2019 中创建一个新的 Class 库 (.NET Framework) 项目,将构建目标设置为 x86(使其与 Delphi 5 兼容)。您为 UnmanagedExports 添加 NuGet 包。
在该项目中添加相同的界面:
[ComVisible(true)]
[Guid("9F5A2431-5559-410C-BAB4-5144CA8C0B7B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IManagedInterface
{
int CheckCredentials(
[MarshalAs(UnmanagedType.BStr)] string contextname,
[MarshalAs(UnmanagedType.BStr)] string container,
[MarshalAs(UnmanagedType.BStr)] string username,
[MarshalAs(UnmanagedType.BStr)] string password);
}
和实现该接口的 class:
public class Class1 : IManagedInterface
{
public int CheckCredentials(string contextname, string container,
string username, string password)
{
var pc = new PrincipalContext(ContextType.Domain, contextname, container);
return Convert.ToInt32(pc.ValidateCredentials(username, password,
ContextOptions.Negotiate));
}
}
最后,您从创建 returns 这个 class:
的 DLL 中导出一个函数
static class Exports
{
[DllExport]
public static void CreateTheInterface(
[MarshalAs(UnmanagedType.Interface)] out IManagedInterface instance)
{
instance = new Class1();
}
}
现在您可以使用 Delphi 中的那个 DLL(为了保持简短,库不是按需加载的,我会在生产代码中这样做):
procedure CreateTheInterface(out AInstance: IManagedInterface); stdcall;
external 'ClassLibrary1.dll';
var
Imi: IManagedInterface;
context, container, username, password: string;
begin
CreateTheInterface(Imi);
if Imi <> nil then try
context := 'testnet.testad.org:636';
container := 'dc=testnet,dc=testad,dc=org';
username := 'someguy';
password := 'password';
Writeln('call returned: ',
Imi.CheckCredentials(context, container, username, password));
except
on E: Exception do
Writeln(E.Message);
end;
Readln;
end.
所以,没有'gotchas'的雷区,真的很简单
我正在更新遗留 Delphi 5 应用程序(我们有代码),该应用程序通过使用用户提供的凭据进行绑定来针对 LDAP/AD 进行身份验证。但是,我们使用的库无法通过端口 636 或 3269 绑定 LDAPS (LDAP/SSL)。
我看到在 C# 中针对 LDAP/AD 进行身份验证可以像这样简单:
PrincipalContext pc = new PrincipalContext(ContextType.Domain, "testnet.testad.org:636", "dc=testnet,dc=testad,dc=org");
bool validated = pc.ValidateCredentials(username, password, ContextOptions.Negotiate);
我正在考虑将必要的调用包装在一个 .DLL 中,然后从 Delphi 应用程序中调用该调用。但是,我假设存在 'gotchas' 的雷区会阻止它变得如此简单。
使用UnmanagedExports这真的很简单。
您从功能的界面开始,如下所示:
type
IManagedInterface = interface
['{9F5A2431-5559-410C-BAB4-5144CA8C0B7B}']
function CheckCredentials(AContextName, AContainerName, AUserName,
APassword: WideString): integer; safecall;
end;
这可能不是参数类型的最佳选择,因为您不能使用 NULL
来调用用户名和密码,并且您可能希望将其他参数(如上下文类型)传递为好吧,但你明白了。
然后在 VS 2019 中创建一个新的 Class 库 (.NET Framework) 项目,将构建目标设置为 x86(使其与 Delphi 5 兼容)。您为 UnmanagedExports 添加 NuGet 包。
在该项目中添加相同的界面:
[ComVisible(true)]
[Guid("9F5A2431-5559-410C-BAB4-5144CA8C0B7B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IManagedInterface
{
int CheckCredentials(
[MarshalAs(UnmanagedType.BStr)] string contextname,
[MarshalAs(UnmanagedType.BStr)] string container,
[MarshalAs(UnmanagedType.BStr)] string username,
[MarshalAs(UnmanagedType.BStr)] string password);
}
和实现该接口的 class:
public class Class1 : IManagedInterface
{
public int CheckCredentials(string contextname, string container,
string username, string password)
{
var pc = new PrincipalContext(ContextType.Domain, contextname, container);
return Convert.ToInt32(pc.ValidateCredentials(username, password,
ContextOptions.Negotiate));
}
}
最后,您从创建 returns 这个 class:
的 DLL 中导出一个函数static class Exports
{
[DllExport]
public static void CreateTheInterface(
[MarshalAs(UnmanagedType.Interface)] out IManagedInterface instance)
{
instance = new Class1();
}
}
现在您可以使用 Delphi 中的那个 DLL(为了保持简短,库不是按需加载的,我会在生产代码中这样做):
procedure CreateTheInterface(out AInstance: IManagedInterface); stdcall;
external 'ClassLibrary1.dll';
var
Imi: IManagedInterface;
context, container, username, password: string;
begin
CreateTheInterface(Imi);
if Imi <> nil then try
context := 'testnet.testad.org:636';
container := 'dc=testnet,dc=testad,dc=org';
username := 'someguy';
password := 'password';
Writeln('call returned: ',
Imi.CheckCredentials(context, container, username, password));
except
on E: Exception do
Writeln(E.Message);
end;
Readln;
end.
所以,没有'gotchas'的雷区,真的很简单