I am trying to create a SQLCLR stored procedure in NET 4.5 that fiddles with ZIP files. Obviously System.IO.Compression
is not on SQL Server's approved list but this is what I get when I try to add it manually via SQL Server Management Studio. The same happens if I try to execute CREATE ASSEMBLY
via a query. Any ideas? Why is this a no-no?
I have also tried running this command in SSMS:
CREATE ASSEMBLY SystemIOCOMPRESSION
FROM 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1\System.IO.Compression.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS
... and the result was the same as when I tried via SSMS UI.
You are trying to import the wrong DLL. That is the "reference" DLL, not the actual "framework" DLL. The following will work as I not only tried it using SQL Server 2012, but I was able to also import System.IO.Compression.FileSystem
and execute System.IO.Compression.ZipFile.CreateFromDirectory()
:
This is needed as you cannot create an
ASYMMETRIC KEY
from the .Net Framework DLLs:ALTER DATABASE [{dbname}] SET TRUSTWORTHY ON;
At minimum you need this:
CREATE ASSEMBLY [System.IO.Compression] FROM N'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.IO.Compression.dll' WITH PERMISSION_SET = EXTERNAL_ACCESS;
If you want to use either the ZipFile or the ZipFileExtensions classes, you will need this (and this one needs to be set to
UNSAFE
, unfortunately):CREATE ASSEMBLY [System.IO.Compression.FileSystem] FROM N'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.IO.Compression.FileSystem.dll' WITH PERMISSION_SET = UNSAFE;
Just in case it is not obvious, your assembly that calls methods in the above mentioned assemblies will also need to have a
PERMISSION_SET
ofEXTERNAL_ACCESS
.And just to be completely clear for anyone who might not be aware of this:
- The
Zip*
classes as well as theSystem.IO.Compression
andSystem.IO.Compression.FileSystem
assemblies are new as of .Net 4.5 - You can only use items new to .Net 4.0 / 4.5 in SQL Server 2012 and 2014 (the current version); SQL Server 2005 / 2008 / 2008 R2 are stuck on the .Net 2.0 series.
- The
I know this is an old question, but I was going down this same path earlier this week of writing a SQLCLR function that could be called by ssrs sql code after generating reports, to package them up in a zip file and email them to users.
After a bunch of research and trial and error, using the ssrs web service interface is the easier and more reasonable approach. You don't have to have to touch the database settings at all to use it and do the exact same thing.
To use it, you add a web reference to the ssrs execution service. You can find out which one you need here. Once you have configured and added your web reference, you can write C#/VB code to render whatever report you want as bytes in the format of your choosing, and save them or do what you wish with them like any other stream of bytes. In our case, we wrote a query to get a list of reports to send by user, rendered all of the reports for that user to temp files by using the api, zipped those temp files, attached them to an email, and sent the email off to the user.
there is a good, trivial example of how to render and save a report to disk with the api here. (code below in case the link dies)
string historyID = null;
string deviceInfo = null;
// Can be XML, NULL, CSV, IMAGE, PDF, HTML4.0, HTML3.2,
// MHTML, EXCEL, and HTMLOWC
string format = "Excel";
Byte[] results;
string encoding = String.Empty;
string mimeType = String.Empty;
string extension = String.Empty;
ReportingExec.Warning[] warnings = null;
string[] streamIDs = null;
ReportingExec.ReportExecutionService re = new ReportingExec.ReportExecutionService();
re.Credentials = System.Net.CredentialCache.DefaultCredentials;
ReportingExec.ExecutionInfo ei = re.LoadReport("/directory/ReportName", historyID);
ReportingExec.ParameterValue[] rptParameters = new ReportingExec.ParameterValue[1];
rptParameters[0] = new ReportingExec.ParameterValue();
rptParameters[0].Name = "DateFormatID";
rptParameters[0].Value = "fr-FR";
re.SetExecutionParameters(rptParameters, "en-us");
results = re.Render(
format, deviceInfo, out extension, out encoding,
out mimeType, out warnings, out streamIDs);
FileStream stream = File.Create("C:\\report.xls", results.Length);
stream.Write(results, 0, results.Length);
stream.Close();
one thing that was confusing to me intially, was where to find the various types above. when you add the web reference to your project, the web reference will have all the necessary types pulled in, in the namespace named after the name you gave your web reference. so if you named your web reference FooService
, all the reporting types would be in namespace FooService
. so you could find FooService.ParameterValue
, FooService.ReportExecutionService
, etc there.
来源:https://stackoverflow.com/questions/24835036/cant-add-system-io-compression-to-trusted-assemblies-in-sql-server