اگر برنامهی شما برای مثال با SMO مربوط به اس کیوال سرور 2008 کامپایل شود، روی سروری با SQL Server 2005 کار نخواهد کرد و پیغام میدهد که نگارش 10 اسمبلی Microsoft.SqlServer.Management.Sdk.Sfc یافت نشد.
یک راه حل آن، نصب Microsoft SQL Server 2008 Management Objects بر روی سرور است، یا راه حل دوم، پیدا کردن اسمبلیهایی که برنامه به آنها ارجاع دارد و کپی کردن آنها کنار فایل اجرایی برنامه در سرور. (درست کردن یک برنامه پرتابل دات نتی، یا نسبتا پرتابل!)
برای این منظور کلاس زیر تهیه شده است که مسیر فایل اجرایی یا dll یک پروژه را دریافت کرده و لیست تمام ارجاعات به آنرا به صورت بازگشتی پیدا میکند. (البته در قسمت یافتن مسیر اسمبلیها، اسمبلیهای سیستمی که با خود دات نت فریم ورک نصب میشوند، حذف شده است)
using System.Collections.Generic;
using System.Reflection;
using System.IO;
namespace App
{
class CFindRef
{
#region Fields (2)
/// <summary>
/// لیستی جهت نگهداری نام اسمبلیها
/// </summary>
private readonly List<string> _assemblies = new List<string>();
/// <summary>
/// لیستی جهت نگهداری مسیر اسمبلیها
/// </summary>
private readonly List<string> _filePath = new List<string>();
#endregion Fields
#region Constructors (1)
/// <summary>
/// سازنده کلاس
/// </summary>
/// <param name="fileName">مسیر اولیه اسمبلی مورد نظر</param>
public CFindRef(string fileName)
{
ListReferences(fileName);
}
#endregion Constructors
#region Properties (2)
/// <summary>
/// لیست مسیر اسمبلیهایی که به آنها ارجاعی وجود دارد منهای موارد سیستمی
/// </summary>
public List<string> ReferencedFiles
{
get
{
_filePath.Sort();
return _filePath;
}
}
/// <summary>
/// لیست کامل اسمبلیهایی که اسمبلی ما به آنها وابسته است
/// </summary>
public List<string> ReferencedNames
{
get
{
_assemblies.Sort();
return _assemblies;
}
}
#endregion Properties
#region Methods (1)
// Private Methods (1)
/// <summary>
/// متدی بازگشتی جهت یافتن لیست ارجاعات
/// </summary>
/// <param name="path">مسیر یا نام اسمبلی</param>
private void ListReferences(string path)
{
//آیا تکراری است؟
if (_assemblies.Contains(path))
return;
Assembly asm;
// آیا فایل است یا نام کامل اسمبلی
if (File.Exists(path))
{
// load the assembly from a path
asm = Assembly.LoadFrom(path);
}
else
{
// سعی در بارگذاری اسمبلی
try
{
asm = Assembly.Load(path);
}
catch
{
asm = null; //جای بهبود دارد
}
}
if (asm == null) return;
// افزودن به لیست نامها
_assemblies.Add(path);
string asmLocation = asm.Location;
//حذف موارد سیستمی از لیست مسیر فایلها
if (asmLocation != null && !asmLocation.Contains("\\System.")
&& !asmLocation.Contains("\\mscorlib"))
_filePath.Add(asmLocation);
// پیدا کردن ارجاعها
AssemblyName[] imports = asm.GetReferencedAssemblies();
// iterate
foreach (AssemblyName asmName in imports)
{
// فراخوانی بازگشتی جهت یافتن تمامی ارجاعات
ListReferences(asmName.FullName);
}
}
#endregion Methods
}
}
مثالی در مورد نحوهی استفاده از آن:
CFindRef cfr = new CFindRef(@"C:\App\test.exe");
foreach (var asmRef in cfr.ReferencedFiles)
{
textBox1.Text += asmRef + Environment.NewLine;
//Application.DoEvents();
}
C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SqlServer.ConnectionInfo\10.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.ConnectionInfo.dll
C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SqlServer.Dmf\10.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.Dmf.dll
C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SqlServer.Management.Sdk.Sfc\10.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.Management.Sdk.Sfc.dll
C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SqlServer.ServiceBrokerEnum\10.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.ServiceBrokerEnum.dll
C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SqlServer.Smo\10.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.Smo.dll
C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SqlServer.SqlClrProvider\10.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.SqlClrProvider.dll
C:\WINDOWS\assembly\GAC_MSIL\Microsoft.SqlServer.SqlEnum\10.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.SqlEnum.dll
برنامه آماده هم در این زمینه موجود است، برای مثال CheckAsm
مشاهده سایت