SQL Server:“为程序集’测试’创建程序集失败,因为程序集’测试’格式错误或不是纯.NET程序集。”

当我尝试将混合模式C ++ / CLI程序集加载到SQL Server 2012时,出现此错误:

CREATE ASSEMBLY [Test] AUTHORIZATION [dbo] from 'H:\test.dll' WITH PERMISSION_SET = SAFE 

Msg 6544,Level 16,State 1,Line 1为程序集’Test’创建程序集失败,因为程序集’Test.dll’格式错误或不是纯.NET程序集。 无法validation的PE标头/本机存根。

SQLCLR程序集中不允许使用混合模式程序集; 只允许纯MSIL程序集。 这在备注部分的CREATE ASSEMBLY的MSDN文档中有所暗示:

assemblyvalidation
SQL Server对CREATE ASSEMBLY语句上载的程序集二进制文件执行检查,以保证以下内容:

  • 汇编二进制文件具有有效的元数据和代码段,并且代码段具有有效的Microsoft中间语言(MSIL)指令。

有关详细信息,请参阅以下答案(此处还有Stack Overflow):

SQL Server自定义CLR失败,并显示错误“无法加载文件或程序集或其中一个依赖项。系统找不到指定的文件。”

特别是指向此限制的SQL Server CLR托管环境中未经测试的.NET Framework程序集的Microsoft KB文章支持策略的链接。

仅允许托管代码的一个可能原因是,允许非托管代码可能会阻止SQL Server对SAFEEXTERNAL_ACCESS级别强制执行某些限制(即主机保护属性等),以及阻止validation。

虽然为UNSAFE设置大会取消了大部分限制,但仍然强制执行:

运行时检查

在运行时,将检查代码程序集是否满足以下条件。 如果找到任何这些条件,则不允许运行托管代码并抛出exception。

不安全

通过从字节数组中调用System.Reflection.Assembly.Load()方法显式加载程序集,或者不允许通过使用Reflection.Emit名称空间隐式加载程序集。

上面的引用来自以下MSDN页面: CLR集成编程模型限制 。

更多信息在: CLR Hosted Environment 。

无法将混合模式C ++ / CLI程序集加载到SQL Server中。

您只能加载“纯”C ++ / CLI程序集:

在此处输入图像描述

但是,可能有办法解决这个问题。 在C#文件中使用P/Invoke 。 这相当于编写混合模式C ++ / CLI程序集包装器,因为当CLR代码调用程序集中的native代码时,它会执行隐式P/Invoke (如果这对您P/Invoke ,请告诉我)。

为什么SQL Server会阻止加载混合模式程序集?

这是我的理论:

如果我们回到2005年,事情会有所不同。 当他们发布第一版SQL Server以支持CLR时,混合模式程序集有时会在加载时死锁。 请参阅Microsoft – 混合DLL加载问题 。 即使在他们解决了这个问题之后,仍然存在围绕安全性和稳定性的争论,这些争论使得允许将混合模式C ++ / CLI程序集加载到SQL服务器的核心中。

如果最初的微软设计团队中的任何人都可以填补空白,我会非常好奇!