MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Как узнать, что под капотом у CLR функции"
Answer 1100050
Функции SQLCLR могут быть представлены либо одной скомпилированной DLL, либо DLL с исходниками, если ее залили таким образом (что стандартный шаблон проекта и делает, насколько я знаю). Перечень функций можно получить запросом
select * from sys.assembly_modules
Который вернет что-то такое:
object_id assembly_id assembly_class assembly_method ... 1573580644 65551 UserDefinedFunctions Func1 ... 1589580701 65551 UserDefinedFunctions Func2 ...
assembly_id указывает на сборку, в которой лежит код функции. Сборки можно получить запросом к системной таблице sys.assemblies. Файлы, соответствующие сборкам, хранятся в sys.assembly_files.
Извлечь С# код из скомпилированной сборки можно с помощью библиотеки ICSharpCode.Decompiler.
Пример запроса для вывода списка файлов:
SELECT assemblies.name, assemblies.assembly_id, assembly_files.name as "filename" FROM sys.assemblies INNER JOIN sys.assembly_files ON assemblies.assembly_id = assembly_files.assembly_id
Пример вывода кода всех файлов указанной сборки на C#:
using System; using System.IO; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Text; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp; class SqlClrAssFile { public string Name { get; set; } public byte[] Data { get; set; } } class Program { public static IEnumerable<SqlClrAssFile> GetAssemblyFiles(string assname) { SqlConnectionStringBuilder build = new SqlConnectionStringBuilder(); build.DataSource = "SERVER"; build.InitialCatalog = "mydb"; SqlConnection conn = new SqlConnection(build.ConnectionString); List<SqlClrAssFile> files = new List<SqlClrAssFile>(); using (conn) { conn.Open(); SqlCommand cmd = new SqlCommand( "SELECT assembly_files.name as filename,content FROM sys.assemblies "+ " INNER JOIN sys.assembly_files ON assemblies.assembly_id = assembly_files.assembly_id " + " WHERE assemblies.name=@name", conn); cmd.Parameters.AddWithValue("name", assname); SqlDataReader rd = cmd.ExecuteReader(); using (rd) { while (true) { if (rd.Read() == false) break; SqlClrAssFile file = new SqlClrAssFile(); file.Name = (string)rd["filename"]; file.Data = (byte[])rd["content"]; files.Add(file); } return files; } } } static void Main(string[] args) { IEnumerable<SqlClrAssFile> files = GetAssemblyFiles("MyClrAssembly"); foreach (var x in files) { Console.WriteLine("*****"+x.Name+ "*****"); string ext = Path.GetExtension(x.Name); if (ext == ".cs") { //показать файл исходников Console.WriteLine(Encoding.UTF8.GetString(x.Data)); } else if (ext == ".dll" || ext == "") { try { //показать декомпилированную DLL string name = Path.GetFileName(x.Name); File.WriteAllBytes(name, x.Data); CSharpDecompiler decompiler = new CSharpDecompiler(name, new DecompilerSettings()); Console.WriteLine("[Decompiled]"); Console.WriteLine(decompiler.DecompileWholeModuleAsString()); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } else { Console.WriteLine("[Unknown file: {0} bytes]",x.Data.Length); } } Console.ReadKey(); } }
Здесь мы просто преобразуем байты в текст для .cs файлов, а для DLL выгружаем в файл и декомпилируем.
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.