1, the introduction

In the development of a project is generally put the reference DLL in the root directory, with the growing of the project, the root directory DLL files will be more and more, reasonable planning of the storage address of these DLLS, can make the whole project more standard and beautiful. This article is about C# how to find files in the specified folder DLL related content, based on the RDIFramework WinForm version of the framework for the introduction of the Web related DLL planning similar, I hope you have a certain reference learning value.

The DLL under the original execution directory of our framework is stored as follows. You can see that there are many files under the whole directory.

The following we through the most commonly used way of DLL file planning processing, so that the whole running directory more clean, standard, the final effect as shown in the following figure.

As you can see, the entire run directory structure is very clean and tidy. How do you do that? Let’s explain it in detail.

2. Implementation method

2.1 system search DLL directory and order

The CLR parses an assembly and searches in a root directory called Probing, which is obviously the directory that contains the current assembly. The AppDomainSetup class stores information about the directory to explore. Its members include ApplicationBase and PrivateBinPath. The program searches for DLLS in the following order (distinguishing between assemblies with strong name signatures and assemblies without strong name signatures) :

  1. The root directory of the program
  2. A subdirectory under the root directory with the same name as the referenced assembly
  3. The subdirectories under the root directory are explicitly defined as private directories
  4. When looking in a directory, if the DLL cannot be found, an exe with the same name will be tried
  5. If the assembly has a culture, rather than language-neutral, it also tries to find subdirectories named after the locale

Assemblies with strong name signatures:

  1. Global assembly cache

  2. If codebase is defined, the codebase definition takes effect, and if the path specified by codebase cannot be found, an error is reported directly

  3. The root directory of the program

  4. A subdirectory under the root directory with the same name as the referenced assembly

  5. The subdirectories under the root directory are explicitly defined as private directories

  6. When looking in a directory, if the DLL cannot be found, an exe with the same name will be tried

  7. If the assembly has a culture, rather than language-neutral, it also tries to find subdirectories named after the locale. As shown below:

2.2. How to let the program recognize DLLS in different directories?

As we can see, the above sequence uses private directories with or without strong name signatures. There are generally three ways to implement programs to identify DLL files in different directories.

1. Configure the privatePath for the app. config file.

2. The subscriber assembly resolves the event AssemblyResolve in the code.

Reset the directory of the current environment before loading the code that uses DLLS.

2.2.1. Configure the app. config file privatePath.

This is the simplest and most common method, and it’s the way we do it. This method has some limitations, that is, it can not control the DLL, and it can not solve the problem that the assembly introduced in the third party DllImprt is not in the root directory. The following configuration is used for multiple directories. Space.

<configuration>
<runtime>
      <! XMLNS is a required feature. Specifies the XML namespace required for assembly binding. Use the string URN: architecture-Microsoft-com: ASM.v1 as the value. -->
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <publisherPolicy apply="yes"/>  <! -- Specify whether the runtime uses publisher policy -->
        <! -- Specifies the subdirectory searched by the common language runtime when the assembly is loaded, where privatePath is the relative path to the *.exe.config file, and multiple folders are separated by semicolons. -->
        <probing privatePath="devLibs; 3rdLibs; frameworkLibs"/>
    </assemblyBinding>
  </runtime>
</configuration>
Copy the code

Where privatePath is the relative path to the *.exe.config file. Multiple folders are separated by semicolons. When compiled, a file with the suffix.exe.config is generated in the build directory, which is relative to this file. After adding the assembly DLL reference, set the DLL property “copy local” to False. During program compilation, DLLS and their dependencies in the Common and Security folders are automatically retrieved.

Our framework is implemented in this way, and the final run directory structure looks like this.

2.2.2 Subscription assembly resolution event AssemblyResolve is resolved in code.

The application assembly domain supports handling during assembly resolution:

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
Copy the code

With this event, we can do different processing depending on the assembly during assembly parsing, such as loading an x86 or 64-bit assembly, and of course specify the assembly directory. This is where methods like assembly.load and assembly.loadFrom come in.

Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    AssemblyName assemblyName = new AssemblyName(args.Name);
    return Assembly.LoadFrom(Path.Combine(baseDirectory, "3rdLibs"));
}
Copy the code

Reset the directory of the current environment before loading the code using DLLS.

This method is through the Environment. The CurrentDirectory = customPath, when such call DLL method, because the directory already switched to the specified directory, we can realize the corresponding DLL loaded correctly. This is a tricky trick that requires switching assembly directories back and forth, but it works great in some cases.

2.3. How to load the assembly in [dllImport]

There are several cases for dllImport.

Write their own dllImport

The referenced C# plug-in in turn uses dllImport

2.3.1 Self-written dllImport

If it is written by yourself, it is very easy to control, you can directly specify the relative directory DllImport(3rdLibs\ nlog.dll). However, this method is not reliable and will not load on some systems. If dllImport is used, the method described below is recommended (the referenced C# plugin uses dllImport).

2.3.2 the referenced C# plugin is used againdllImport

Since you cannot change the path, you can only change the path of the current program using the above special method. Of course, it is easier to add a record in the system environment pointing to the directory of the DLL to be loaded. Because in C++ code, the Windows directory and the Windows\System32 directory and the environment variable set directory are one of the search paths. Here’s how to modify system environment variables from C# :

static void AddEnvironmentPaths(IEnumerable<string> paths)
{
    var path = new[] { Environment.GetEnvironmentVariable("PATH") ?? string.Empty };
    string newPath = string.Join(Path.PathSeparator.ToString(), path.Concat(paths));
    Environment.SetEnvironmentVariable("PATH", newPath);
}
Copy the code

The above is the whole content of this article, I hope the content of this article for everyone’s study or work has a certain reference learning value.

3. Operation effect

4. Refer to the article

4.1. Relevant articles

  • Assembly binding element for runtime

  • Discussion on dynamic loading of assembly in.net

  • Register to use GAC — Global Assembly Cache (.NET)

  • Again, how the CLR finds and loads assemblies, find assemblies

  • In-depth understanding of CLR class loading mechanisms

  • C# assembly loading method

4.2 framework related

RDIFramework.NET V3.6 is a new release with 100% source authorization

RDIFramework.NET – Based. NET rapid information system development framework – series directory

RDIFramework.NET Agile development framework ━ Workflow components

RDIFramework.NET SOA solution (distributed as Windows services, WinForm and IIS) – distributed applications

Wechat public number development series – play wechat development – catalog summary

The most comprehensive SignalR series tutorial ever – catalog summary

RDIFramework.NET Agile development framework ━ Workflow component Web service platform

RDIFramework.NET Agile Development framework integrates instant Messaging (IM) with SignalR technology

RDIFramework.NET framework based on Quartz.Net to achieve task scheduling details and effect display

RDIFramework framework integration of wechat development application effect display


Over the years, thanks to supporters and users of the RDIFramework.NET framework, you can find out more at the following address.

RDIFramework.NET official website: www.rdiframework.net/

RDIFramework.NET official blog: blog.rdiframework.net/

At the same time need to explain, all technical articles in the future to the official website prevail, welcome everyone to collect!

RDIFramework.NET is built by the professional team of Hainan Guosi Software Technology Co., LTD., which has been updated for a long time. Please feel free to use it!

Please follow the official wechat account of RDIFramework.net (wechat id: Guosisoft) to keep abreast of the latest developments.

Scan the QR code for immediate attention