There is a solution with two projects.

  • DLL library

  • WPF application using DLL in References

When compiling a WPF project, the DLL is placed in the folder with the EXE . However, for reasons beyond my control, it is necessary that the WPF application look for this DLL in the [Π½ΠΎΠΌΠ΅Ρ€ вСрсии] folder in the application folder, ie:

If the application is located in the folder c:\MyProject\project.exe , and the file version 1.0.3.24 means that the DLL will be located in c:\MyProject\1.0.3.24\MyLibrary.dll

Here is my solution:

The Build Action property of App.xaml set to Page , and the code is added to App.xaml.cs

 [STAThread] public static void Main() { try { //Π‘Π΅Ρ€Ρ‘ΠΌ Assembly прилоТСния System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); //Π‘Π΅Ρ€Ρ‘ΠΌ ΠΏΠ°ΠΏΠΊΡƒ прилоТСния string appDirectory = System.IO.Path.GetDirectoryName(assembly.Location); //Π‘Π΅Ρ€Ρ‘ΠΌ Π²Π΅Ρ€ΡΠΈΡŽ прилоТСния string appVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location).FileVersion; //ВычисляСм ΠΏΠ°ΠΏΠΊΡƒ с DLL string dllpatch = System.IO.Path.Combine(appDirectory, appVersion); //Π‘Π΅Ρ€Π΅ΠΌ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ окруТСния PATH string environmentPATH = Environment.GetEnvironmentVariable("PATH"); //УстанавливаСм ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ окруТСния PATH Environment.SetEnvironmentVariable("PATH", environmentPATH + ";" + dllpatch, EnvironmentVariableTarget.Process); //ЗапускаСм ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ var application = new App(); application.InitializeComponent(); application.Run(); } catch (Exception ex) { //Π­Ρ‚Π° строка Π½Π΅ срабатываСт, Exeption Π½Π΅ отлавливаСтся System.Diagnostics.EventLog.WriteEntry("MyApplication", ex.Message + "\n" + ex.StackTrace, System.Diagnostics.EventLogEntryType.Error); } } 

However, when you run the project, everything is fine, but as soon as I put the dll in the above folder try catch does not work, the application falls into an exception, and the Windows log is displayed:

Application: project.exe Platform Version: v4.0.30319 Description. The process was terminated due to an unhandled exception. Exception Details: System.IO.FileNotFoundException
in MyNameSpace.App.Main ()

2 answers 2

Try using codeBase in app.config.

 <configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="myAssembly" publicKeyToken="32ab4ba45e0a69a1" culture="en-us" /> <codeBase version="2.0.0.0" href="http://www.litwareinc.com/myAssembly.dll"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration> 

There is still <probing> . It can specify directories for search assemblies.

 <configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <probing privatePath="bin;bin2\subbin;bin3"/> </assemblyBinding> </runtime> </configuration> 
  • <dependentAssembly> <assemblyIdentity name="FirebirdSql.Data.FirebirdClient" publicKeyToken="3750abcc3150b00c" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.9.0.0" newVersion="5.9.0.0" /> </dependentAssembly> - Andrew NOP
  • Something like this when the version is unknown - Andrey NOP
  • Made a skipt on PostScript, Replaces the string with a folder in the config depending on the version after compilation. Everything works out with a bang! - Dmitry Chistik

AssemblyResolve event

The AssemblyResolve event allows you to intervene in the process and manually load an assembly that the CLR cannot find. If this event is handled, then referenced assemblies can be distributed to different locations and still load them.
Inside the AssemblyResolve event handler, the assembly is searched for and loaded by calling one of the three static methods of the Assembly class: Load , LoadFrom or LoadFile . These methods return a reference to the newly loaded assembly, and this reference is then returned to the calling code:

 static void Main() { AppDomain.CurrentDomain.AssemblyResolve += FindAssembly; ... } static Assembly FindAssembly (object sender, ResolveEventArgs args) { string fullyQualifiedName = args.Name; Assembly Π° = Assembly.LoadFrom(...); return Π°; } 

Ps. Yes, this is an unusual event - it has a return type. If there are many handlers, the first handler, which returned a non- null Assembly object, takes precedence.

Literature:
Albahari, Joseph, Albahari, Ben.
With # 6.0. Directory. Full language description, 6th ed. : Trans. from English - M.: β€œID Williams” LLC, 2016. - 1040 pp., Ill. - Paral. tit English
ISBN 978-5-8459-2087-4 (rus.)

  • I wrote that even in Main does not enter, i.e. subscribing to FindAssembly fails. = (I tried this option too, it didn't work out. - Dmitry Chistik
  • In theory, the assembly should be loaded at the moment when it is first needed - Andrey NOP
  • I thought so too, however .Net thinks otherwise. At least in WPF - Dmitry Chistik