۱۳۸۸/۰۱/۲۵

يافتن ليست اسمبلي‌هاي ارجاعي


اگر برنامه‌ي شما براي مثال با 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();
}
براي نمونه، برنامه‌اي كه از SMO‌ مربوط به اس كيوال سرور 2008 استفاده مي‌كند، اين ليست ارجاعات را دارد:

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
با كپي كردن همين فايل‌ها كنار فايل اجرايي برنامه‌اي كه قرار است روي سروري با SQL Server 2005 كار كند، مشكل برطرف مي‌شود و برنامه بدون مشكل كار خواهد كرد.

برنامه آماده هم در اين زمينه موجود است، براي مثال CheckAsm
مشاهده سايت