2011-03-10 13 views
7

Belirli bir Satıcıdan bazı üçüncü parti meclislerini referans gösteren ve kullanan bir uygulama geliştiriyorum; geliştirme kutusunda kaynak ağacımda bir referans klasöründe bu 3 derlemeler var ve bunları başvuruda bulunabilir ve uygulamayı yapılandırabilir, uygulama oluşturur, ancak tüm sunucu uygulaması yüklü olmadığından çalışmaz, ancak bu iyi. Bu özel bir uygulama kopyalamak ve referans ediyorum tüm montajlar gibi klasör şey vardır çalıştırmak istediğiniz sunucudaBaşka bir klasördeki montaj referanslarını çözün

:

D:\ProgramFiles\VendorName\ProductName\Support\API\Bin64 

ve ben bu klasöre benim küçük yürütülebilir kopyalayıp, bunu çalıştırmak eğer mükemmel çalışıyor ama ben gibi daha uygun bir klasöre benim .exe koyarsanız istiyorum:

D:\ProgramFiles\MyCompanyName\MyProduct\bin\... 

çalışmıyor bu o meclisleri çözülemiyor çünkü.

Biliyorum, exe'm referansları aramasını istediğiniz klasörleri belirtmek için app.config'te probu kullanabiliyorum, ancak derlemeler, bir alt klasörde değil, tamamen farklı bir konumda.

Tüm satıcı derlemelerini uygulama klasörümde kopyalamak istemiyorum ve yalnızca referanslarımı gönderemediğim 3 tane koyamıyorum çünkü bunlar başka meclisleri de yüklüyorlar ve hepsine sahip olmadıkça (birçok ...) , İşe yaramıyor.

Özel bir şey yapmıyorum, uygulama etki alanları oluşturmuyorum ve yansıtma yoluyla derlemeleri yüklemiyorum, sadece CLR'nin başvuruları başlatma veya yürütme sırasında gerektikçe başvuruları çözmesi için istiyorum.

Teşekkürler.

Düzenleme: Burada nihai çalışma kodu

static System.Reflection.Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
{ 
    Logger logger = new Logger(); 

    try 
    { 
     string RMSAssemblyFolder = ConfigurationManager.AppSettings["RMSAssemblyFolder"]; 

     Assembly MyAssembly = null; 
     string strTempAssmbPath = string.Empty; 

     Assembly objExecutingAssemblies = Assembly.GetExecutingAssembly(); 
     AssemblyName[] arrReferencedAssmbNames = objExecutingAssemblies.GetReferencedAssemblies(); 

     AssemblyName myAssemblyName = Array.Find<AssemblyName>(arrReferencedAssmbNames, a => a.Name == args.Name); 

     if (myAssemblyName != null) 
     { 
      MyAssembly = Assembly.LoadFrom(myAssemblyName.CodeBase); 
     } 
     else 
     { 
      strTempAssmbPath = Path.Combine(RMSAssemblyFolder, args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll"); 

      if (!string.IsNullOrEmpty(strTempAssmbPath)) 
      { 
       if (File.Exists(strTempAssmbPath)) 
       { 
        logger.Information("Assembly to load: {0} - File was found in: {1}", args.Name, strTempAssmbPath); 

        // Loads the assembly from the specified path.     
        MyAssembly = Assembly.LoadFrom(strTempAssmbPath); 
       } 
      } 
     } 

     // Returns the loaded assembly. 
     return MyAssembly; 
    } 
    catch (Exception exc) 
    { 
     logger.Error(exc); 
     return null; 
    } 
} 
+0

olası yinelenen http://stackoverflow.com/questions/1373100/how-to-add-folder-to-assembly-search-path-at-runtime-in-net – nawfal

cevap

12

DLL montaj çözünürlüğünü kanca AppDomain.AssemblyResolve kullanabilir ve bu klasörden istenen meclisleri yüklemeyi deneyin ardından yüklenir tezler nerede Önce klasörü bulmalısınız.

Böyle bir şey olacaktır (test edilmedi ve versiyonunu ve tipi adıyla birlikte güçlü isim içerebilir, args.Name tam ihtiva kontrol etmek gerekir):

var otherCompanyDlls = new DirectoryInfo(companyFolder).GetFiles("*.dll"); 

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => 
{ 
    var dll = otherCompanyDlls.FirstOrDefault(fi => fi.Name == args.Name); 
    if (dll == null) 
    { 
     return null; 
    } 

    return Assembly.Load(dll.FullName); 
}; 
+0

Teşekkürler, ben kullanarak düzeltildi senin fikrin ve edi'deki kodum ted soru ve şimdi iyi çalışıyor :) –

+0

Şüphesiz benim çözüm optimize edilebilir, özel bir klasörde bir derleme bulunamazsa, bu yöntemin null döndürüp döndürmeyeceğinden emin değilim ve eğer öyleyse, CLR yine de GAC, örneğin fark ettim çünkü bu yöntem de System.XML.Serializer gibi meclisler için çağrılır ...Bunu bir netTcp bağlı WCF Hizmeti'ni barındıran bir konsol uygulamasında test ediyorum, şimdi çalışıyor ve uygulamayı herhangi bir klasörden çalıştırabilirim, sonunda WCF'yi barındırmak için bir WindowsService oluşturacağım. Tekrar teşekkürler.)) –

+0

Coo, teşekkürler. Bunu birkaç gün içinde deneyeceğim. – Tarion

0

Kullanım SN.exe: SN -T VendorAssembly.dll, bu ortak anahtar belirteci olan bir altıgen sayı döndürür, o zaman, uygulamadan derleme başvurusu .Config. Versiyonu almak için sağlayıcınızın kurulumunu tıklayın ve bunu codeBase sürüm değeri için kullandığınız href = yolunu kullanın.

<configuration> 
     <runtime> 
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
      <dependentAssembly> 
       <assemblyIdentity name="VendorAssembly" culture="neutral" publicKeyToken="307041694a995978"/> 
       <codeBase version="1.1.1.1" href="FILE://D:/ProgramFiles/VendorName/ProductName/Support/API/Bin64/VendorAssembly.dll"/> 
      </dependentAssembly> 
      </assemblyBinding> 
     </runtime> 
    </configuration> 
+0

Merhaba, işe yaramasaydı, hala FileNotFound istisnasını alırım ... Ben güçlü bir şekilde adlandırılan referans değil, SN -t işe yaramadı ama istisna mesajından PublicKeyToken gördüm, bu yüzden onun değerini buradan kopyaladı, hala çözülemez ... :( –

İlgili konular