从SQL Server 2008调用非托管的C/C++ DLL函数

5
我有一个大型的C/C++函数库,需要从SQL Server 2008中调用。我编写了一个C#适配器类,通过DllImport从Win32 DLL中加载这些函数并将其暴露给.Net代码,在大多数.Net应用程序中,这个方法都能正常工作。现在,我尝试使用相同的技术来使用SQL Server CLR,创建了一组CLR函数和存储过程,它们调用适配器类。但是这个方法无法运行,因为尝试加载非托管DLL会导致System.BadImageFormatException异常。我可以使用扩展存储过程来完成这项任务,但这种方法已经被弃用,并且在任何新版本的SQL Server中都可能被停用。正确的调用CLR存储过程中非托管函数的方法是什么?我的猜测是这应该在进程外部完成。
我正在尝试让我的存储过程调用公开这些函数的Web服务。听起来不错,但是到目前为止,我在部署使Web服务调用的SQLCLR程序集时遇到了问题。我无法加载 System.ServiceModel.dll 版本3.0.0.0 的程序集,它依赖于 System.Web.dll 版本2.0.0.0 的程序集。 加载 System.Web 程序集时,出现以下错误:
Assembly 'System.Web' 引用了程序集 'system.web, version=2.0.0.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a.',但该程序集在当前数据库中不存在。SQL Server 尝试查找并从引用程序集的相同位置自动加载所引用的程序集,但该操作失败(原因:版本、文化或公钥标记不匹配)。请将所引用的程序集加载到当前数据库中,并重试请求。 我已经找到了解决部署 System.Web 程序集的问题的方法。应该从 C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Web.dll 部署它,而不是从 C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.dll 部署它。然后所有其他必需的程序集也会得到部署。
以下是按照部署顺序列出的程序集: - C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\SMdiagnostics.dll - C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Web.dll - C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Messaging.dll - C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\System.IdentityModel.dll - C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\System.IdentityModel.Selectors.dll - C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\Microsoft.Transactions.Bridge.dll

你是否正在尝试将一个32位的非托管dll加载到一个64位的服务器中? - GSerg
作为一个附带参考,这可能是在进程外完成的,但我相信这不是必需的。 - GSerg
好的,我需要以任何可能的方式完成它。是的,32位未托管代码,我相信服务器是32位的,但在64位操作系统上运行。 我看到了那篇帖子。他们正在使用即将被弃用的扩展存储过程。 - Ramzay
我已经找到了部署 System.Web 程序集的问题的解决方案。不应该从 'C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.dll' 部署它,而是应该从 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Web.dll' 部署它。然后所有其他必需的程序集也会被部署。 - Ramzay
1
你的评论显示了两个问题:1)你似乎正在使用FW 3.0,然而SQL Server 2008仅支持2.0;2)你似乎从Framework64加载程序集,这意味着你有一个64位服务器,在其中你无法加载32位本机程序集。 - GSerg
显示剩余4条评论
1个回答

1

这里有一个有趣的讨论: MSDN - SQL CLR中的非托管代码。我怀疑这是由于引擎加载DLL的方式导致的。它们提供了一系列选项,包括在SQL Server之外的另一个服务中托管代码并使用WCF或者COM访问代码。最后一个选择是将您的代码重新编译为纯托管C++,但这可能不适用于旧代码。

了解SQL Server 2005中的CLR集成提供了更多关于该过程如何工作的信息。

为了进一步限制允许存在和执行的代码,每个程序集必须注册一组权限。可以使用三个预定义的集合:SAFE、EXTERNAL_ACCESS和UNSAFE...

您还应该查看CLR集成安全,并确定执行代码所需的信任级别以及您是否能够在CLR进程中访问和使用该代码。


谢谢。这很有趣,但并没有提供解决方案。 - Ramzay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接