Sql 2005 CLR 集成 - 是否支持动态程序集加载?

发布于 2024-08-11 04:19:10 字数 1812 浏览 4 评论 0原文

我有一个静态类,它动态加载 .NET 程序集(使用 Assembly.LoadFile 方法) 我收到以下错误消息:

Msg 6522, Level 16, State 2, Line 3
A .NET Framework error occurred during execution of user-defined routine or aggregate "MySQLCLRUDFFunction": 
System.TypeInitializationException: The type initializer for 'MyClassName' threw an exception. ---> System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed

当我尝试使用此声明分配 CAS 安全性时,

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]

我反而得到此异常

Msg 6522, Level 16, State 2, Line 2
A .NET Framework error occurred during execution of user-defined routine or aggregate "MySQLCLRUDFFunction": 
System.TypeInitializationException: The type initializer for 'MyClassName' threw an exception. ---> System.Security.SecurityException: Request failed.

注意:我已向我的 SQL Server 服务帐户授予对磁盘上的动态程序集文件的“完全访问权限”。我使用语法复制了动态程序集:

create Assembly TestAssembly
    From 'C:\MyTestAssembly.dll';
--Alter Assembly to copy dynamic assembly file
Alter Assembly TestAssembly add file from 'C:\mydynamicassembly.dll';

在打开 TRUSTWORTHY ON 并设置 PERMISSION_SET = UNSAFE 后,我现在收到此异常

Msg 6522, Level 16, State 2, Line 2
A .NET Framework error occurred during execution of user-defined routine or aggregate "MySQLCLRUDFFunction": 
System.TypeInitializationException: The type initializer for 'MyClassName' threw an exception. ---> System.IO.FileLoadException: LoadFrom(), LoadFile(), Load(byte[]) and LoadModule() have been disabled by the host.

I have a static class which loads a .NET assembly dynamically (using Assembly.LoadFile method)
I get the following error message:

Msg 6522, Level 16, State 2, Line 3
A .NET Framework error occurred during execution of user-defined routine or aggregate "MySQLCLRUDFFunction": 
System.TypeInitializationException: The type initializer for 'MyClassName' threw an exception. ---> System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed

.

When I try assign CAS security using this declaration

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]

I instead get this exception

Msg 6522, Level 16, State 2, Line 2
A .NET Framework error occurred during execution of user-defined routine or aggregate "MySQLCLRUDFFunction": 
System.TypeInitializationException: The type initializer for 'MyClassName' threw an exception. ---> System.Security.SecurityException: Request failed.

Note: I have given my SQL Server service account "Full Access" to my dynamic assemly file on disk. I copied my dyamic assembly using syntax:

create Assembly TestAssembly
    From 'C:\MyTestAssembly.dll';
--Alter Assembly to copy dynamic assembly file
Alter Assembly TestAssembly add file from 'C:\mydynamicassembly.dll';

After turning TRUSTWORTHY ON and setting PERMISSION_SET = UNSAFE I now get this exception

Msg 6522, Level 16, State 2, Line 2
A .NET Framework error occurred during execution of user-defined routine or aggregate "MySQLCLRUDFFunction": 
System.TypeInitializationException: The type initializer for 'MyClassName' threw an exception. ---> System.IO.FileLoadException: LoadFrom(), LoadFile(), Load(byte[]) and LoadModule() have been disabled by the host.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

二手情话 2024-08-18 04:19:10

正如错误消息所述,即使在不安全的情况下,SQL Server 也完全不允许动态程序集加载。 Assembly.Load 调用成功的唯一方法是程序集已通过 CREATE ASSEMBLY 加载到数据库中或 GAC 中以及 支持的(“blessed”)程序集列表sqlclr 博客上还有另一篇关于此问题的文章

As the error message states, dynamic assembly loading is completely disallowed by SQL Server - even under unsafe. The only way for Assembly.Load calls to succeed is if the assembly is already loaded in the database via CREATE ASSEMBLY or in the GAC and on the list of supported ("blessed") assemblies. There is another post on this on the sqlclr blog.

巴黎夜雨 2024-08-18 04:19:10

我知道这是一个非常老的问题,但我最近找到了一种方法来实现你想要的。当您尝试在 SQL CLR 托管程序集中使用 Assembly.Load(...) 时,它会显式失败,这是设计使然,即使使用 PERMISSION_SET = UNSAFE 也是如此。这是为了保证数据库服务器的稳定性。

加载动态程序集的技术是首先注册它们,然后使用传入完全限定类型名称(包括程序集版本信息)的 Type.GetType(...) 解析类型。

以下是步骤:

1.编译类型,并在磁盘上完成(即不创建内存中程序集)。CompilerResults 类型将具有 CompiledAssembly 属性和 PathToCompiledAssembly。 属性。访问 CompiledAssembly 属性将尝试使用 Assembly.Load

2.使用该路径,我从代码中调用存储过程。 (使用 new SqlConnection("Context Connection = true")),我传入程序集的名称(我已预先确定)和编译的程序集路径:

CREATE PROCEDURE re.CreateAssembly
    @name VARCHAR(100),
    @path VARCHAR(1000)
AS
BEGIN
    DECLARE @sql NVARCHAR(2000)
    SET @sql = N'CREATE ASSEMBLY [' + @name + '] AUTHORIZATION [DatabaseUser] FROM ''' + @path + ''' WITH PERMISSION_SET + SAFE';
    EXEC sp_executesql @sql;
END
GO

3.使用您预先确定的名称,您可以使用 Type.GetType(...),例如:

string typeName = "MyCompiledAssembly.MyClass, MyCompiledAssembly, Version=0.0.0.0, Culture=Neutral, PublicKeyToken=null, ProcessorArchitecture=MSIL";
Type type = Type.GetType(typeName);

当 SQLCLR 尝试解析类型时,它应该找到它,因为在步骤 2 中您已经向 Sql Server 注册了程序集。

I know this is a very old question now, but I have recently found a way to achieve what you want. When you try and using Assembly.Load(...) in a SQL CLR hosted assembly, it will explicitly fail, this is by design, even with PERMISSION_SET = UNSAFE. This is to ensure the stability of the database server.

The technique to loading your dynamic assemblies, is to register them first and then resolve the type using Type.GetType(...) passing in the fully qualified type name (including assembly version information.

Here are the steps:

1.Compile the type, and finalise on disk (i.e. do not create in-memory assemblies). The CompilerResults type will have a CompiledAssembly property and PathToCompiledAssembly property. Use the latter as accessing the CompiledAssembly property will attempt to use Assembly.Load.

2.Using the path, I call a stored procedure from my code (using new SqlConnection("Context Connection = true")) which I pass in the name of the assembly (which I have predetermined) and the compiled assembly path:

CREATE PROCEDURE re.CreateAssembly
    @name VARCHAR(100),
    @path VARCHAR(1000)
AS
BEGIN
    DECLARE @sql NVARCHAR(2000)
    SET @sql = N'CREATE ASSEMBLY [' + @name + '] AUTHORIZATION [DatabaseUser] FROM ''' + @path + ''' WITH PERMISSION_SET + SAFE';
    EXEC sp_executesql @sql;
END
GO

3.Using your predetermined name, you can use Type.GetType(...), e.g.:

string typeName = "MyCompiledAssembly.MyClass, MyCompiledAssembly, Version=0.0.0.0, Culture=Neutral, PublicKeyToken=null, ProcessorArchitecture=MSIL";
Type type = Type.GetType(typeName);

When the SQLCLR attempts to resolve the type, it should find it, because in step 2 you've already registered the assembly with Sql Server.

夜雨飘雪 2024-08-18 04:19:10

我猜当您执行 CREATE ASSEMBLY 时,您已将 PERMISSION_SET 设置为 SAFE (如果您未指定它,这将是默认值)。如果您想执行此操作,则需要将其更改为 EXTERNAL_ACCESS 或 UNSAFE。

http://msdn.microsoft.com/en-us/library/ms189524。 ASPX

I'm guessing you've got the PERMISSION_SET set to SAFE when you did CREATE ASSEMBLY (this will be the default if you didn't specify it). You'll need to change it to EXTERNAL_ACCESS or UNSAFE if you want to do this.

http://msdn.microsoft.com/en-us/library/ms189524.aspx

时光匆匆的小流年 2024-08-18 04:19:10

我是 Microsoft 的开发人员之一,致力于 SQL-CLR 集成,所以我也许能提供帮助。

要实现您想要的效果,您需要做两件事:

  1. 将数据库标记为可信
  2. 将程序集标记为不安全(数据库必须可信)
  3. SQL Server 运行所在的帐户必须有权访问文件系统上的文件。通常,文件位于网络共享上,但 SQL Server 是在无权访问网络的本地帐户下运行的,因此这通常是一个问题。默认安装的 SQL Express 没有 C: 的权限。

请注意,执行所有这些操作会产生一些负面影响:

  1. 严重的安全隐患 - 您实际上将对实例的控制权放弃给不安全汇编中的代码,因为它现在可以使用原始指针来访问/更改引擎中的任何内容。
  2. 稳定性——出于同样的原因,你也放弃了稳定性保证。
  3. 可移植性和灾难恢复 - 如果您的数据库必须移动到其他地方以进行负载平衡,或者在机器故障后从备份中恢复,则新机器上将不会有 mydynamic assembly.dll。

如果可能的话,请考虑重新设计您的应用程序,以便将所有需要的程序集预先加载到数据库本身中。

[编辑:如果以上都没有帮助,最好在 MSDN 论坛上提问]。

I was one the developers @ Microsoft who worked on SQL-CLR integration, so I may be able to help.

To achieve what you want you need to do two things:

  1. Mark data base as TRUSTWORTHY
  2. Mark assembly as UNSAFE (database must be trustworthy)
  3. The account under which SQL Server runs must have permissions to access the file on the the file system. Often times the file is on a network share but SQL Server is run under local account that has no permission to access network, so this is often a problem. SQL Express in itse default installation does not have rights to C:.

Note that doing all those things has several negative side-effects:

  1. serious security implications - you are effectively ceding control over the instance to the code in unsafe assembly as it can now use raw pointers to access/change anything in the engine.
  2. Stability - you're also ceding stability guarantees for the same reasons.
  3. Portability and disaster recovery - if you database has to move elsewhere for load-balancing or is restored from backup after machine failure you will not have the mydynamicassembly.dll on the new machine.

If at all possible, consider redesigning your app so that all needed assemblies are pre-loaded into the database itself.

[EDIT: if none of the above helps it best to ask on MSDN forums].

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文