是否可以找出用于在 SQL SERVER CLR 中加载程序集的原始路径?

Is it possible to find out the original path that was used to load the assembly in SQL SERVER CLR?

我对在 SQL Server

中使用程序集 CLR 还很陌生

我有一个数据库,其中有很多

是否可以找出用于加载程序集的原始路径?

考虑到这是创建程序集的方式,我需要“来自”路径

CREATE ASSEMBLY ClassLibrary1 
from 'D:\DotNetTeam\SQLServer\ClassLibrary1.dll' 

我问这个是因为这个程序集:a798b6eb4255719355458f3749073dc1b 在服务器列表中找不到并且被报告为不安全(我知道我必须签署它,但为此我需要先找到它)

我发现了这个问题,但这不是我需要的。 How to find the assembly registered in SQL Server?

更新

查询 sys.assembly_files table,我注意到记录存在于那里但不在左侧(对象资源管理器:程序集),我需要重新创建程序集吗?

select * 
from sys.assembly_files
where name like 'a79%'

这个问题的解决方案也可以帮助您解决这些问题
错误:

System.IO.FileLoadException: Could not load file or assembly 'ASSEMBLY_NAME, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. An error relating to security occurred. (Exception from HRESULT: 0x8013150A)

System.IO.FileLoadException: Could not load file or assembly 'ASSEMBLY_NAME, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. Exception from HRESULT: 0x80FC80F1

是,但是如果程序集是从文件系统上的 DLL 加载的,不是通过提供 VARBINARY 文字/十六进制字节。从外部DLL加载时(我强烈推荐反对的方法,btw),原始路径存储在sys.assembly_files中的[name]列中。

执行以下命令以显示任何可能的路径:

-- Change this to the assembly name or path to apply filter:
DECLARE @AssemblyName NVARCHAR(260) = '';
    
-- The content can be used to export the DLL:
SELECT asm.[name] AS [Assembly],
       afl.[name] AS [PathOrAltName],
       asm.[permission_set_desc],
       afl.[file_id],
       afl.[content]
FROM   sys.assembly_files afl
INNER JOIN sys.assemblies asm
        ON asm.[assembly_id] = afl.[assembly_id]
WHERE asm.[name] LIKE N'%' + @AssemblyName + N'%'
OR    afl.[name] LIKE N'%' + @AssemblyName + N'%'
ORDER BY asm.[name], afl.[file_id];

如果程序集是从 VARBINARY 文字/十六进制字节(即 0x4D5A9000...)加载的,则 sys.assembly_files 中的 [name] 列应与sys.assemblies 中的 [name] 列(这是 CREATE ASSEMBLY 语句中使用的名称)。


Querying the sys.assembly_files table, I notice that the record exists there but not on the left side

需要明确的是,问题中的两个屏幕截图都清楚地显示了一长串命名非常糟糕(并且在编程上很明显)的程序集。无论如何,如果一个条目不存在于 sys.assemblies.[=41= 中,它就不可能出现在 sys.assembly_files(或任何其他 assembly-related 管理视图)中]

另外:您确定您在查询 window 中与您在对象资源管理器中 drilling-down 处于同一数据库中吗?

they only provided me a database backup

程序集实际存在于执行 CREATE ASSEMBLY 的每个数据库中,并显示在 sys.assembliessys.asssembly_files 和其他一些系统目录视图中。这是 SQLCLR 的众多好处之一:程序集不在数据库外部,就像现在已弃用的外部存储过程 API / 功能(即 XPs)一样。

I know I have to sign it...

那么我假设您正在将 pre-SQL Server 2017 数据库恢复到 SQL Server 2017 或更新版本。在这种情况下,您确实需要签署所有未签名的程序集,但是不需要需要导出它们才能执行此操作(一个极其常见的误解由于 Microsoft 自己误解了问题,因此提供了有关此主题的错误文档)。这很容易解决,因为您可以签署程序集 in-place 以通过新的“CLR strict security”崩溃:

SQLCLR vs. SQL Server 2017, Part 4: “Trusted Assemblies” – The Disappointment (Msg 10314)

步骤总结如下:

  1. 使用 CREATE CERTIFICATE ...
  2. 在包含程序集的数据库中创建证书(使用密码)
  3. 使用 ADD SIGNATURE TO Assembly::[{assembly_name}] ...
  4. 签署大会
  5. 将证书复制到 [master](但不是私钥!)
  6. 从证书创建登录
  7. 授予signature-based登录UNSAFE ASSEMBLY权限
  8. 您仍然需要确保每个程序集都具有正确的 PERMISSION_SET 它需要做的事情

这是那篇文章中的演示脚本,您可以复制和调整以满足您的需要:

Avoiding "Trusted Assemblies" - Demo(在 PasteBin 上)


有关使用 SQLCLR 的更多信息,请访问:SQLCLR Info

更新(来自 O.P。):

问题是程序集的名称是 ComputeHashFuncAssmembly 但路径是包含 a798b6eb4255719355458f3749073dc1b 的路径,所以 ALTER ASSEMBLY 是需要的。这也是它在左侧不可见的原因,因为它在 ComputeHashFuncAssmembly 下,而不是十六进制代码。

我导出了程序集,因为原始DLL没有提供给我,我想拥有它。

这些是签署程序集的步骤

USE [yourDatabase];
GO

CREATE CERTIFICATE [AssemblyCertificate]
ENCRYPTION BY PASSWORD = 'aPasswordYouChoose'
WITH SUBJECT = 'Assembly Certificate';

ADD SIGNATURE TO Assembly::[ComputeHashFuncAssmembly]
    BY CERTIFICATE [AssemblyCertificate]
    WITH PASSWORD = 'aPasswordYouChoose';

ALTER ASSEMBLY ComputeHashFuncAssmembly
    WITH PERMISSION_SET = SAFE;

-- Copy the certificate to the master
BACKUP CERTIFICATE [AssemblyCertificate] TO FILE = 'C:\temp\certificate.cer';

USE [master];
GO

-- DROP certificate [AssemblyCertificate];
CREATE CERTIFICATE [AssemblyCertificate]
FROM FILE ='C:\temp\certificate.cer';

CREATE LOGIN [login_AssemblyCertificate]
FROM CERTIFICATE [AssemblyCertificate];

GRANT UNSAFE ASSEMBLY TO [login_AssemblyCertificate];