DLL reference location - c#

Okay, I asked this question the other day, and it was closed due to my vagueness. I'll try to be more specific. In a project, say C# (using Visual Studio), I add a reference to a dll (right-click References->Add Reference), and the location of said dll is in C:\Blah\Foo. Now, if I move the exe that is built over to another machine, will the location of the dll need to be with the exe, or will it need to be in C:\Blah\Foo? Thank you.

When you add a reference in the way you've described it is copied to the output folder (same as the exe file). Look in the properties of the reference (F4) and you will see an option called "Copy Local", if this is set to true then the DLL will be copied to the same output folder as the EXE file.
So when you deploy your application to another machine you will need to copy the exe and all it's referenced DLLs to the deployment location. Windows will search for DLLs in a number of locations, the first of which is the same folder as the EXE file.

Typically, you'll just put the assemblies in the same folder as the application, which causes it to be in the default probing path, and get found (for most applications), but there are many other options depending on the type of application. When you define your reference, there is the option to "Copy Local" - which causes the assembly to be copied to the application's output folder. If you leave this set to True, the assembly (DLL) will be with the .exe, and typically "just work."
The full process the runtime uses is covered on MSDN in How the Runtime Locates Assemblies. In particular, the topic titled Locating the Assembly through Codebases or Probing covers how the assemblies are located in detail, which depends on a lot of factors.

The DLL should be with exe file. Have a look on this link to see where .NET serach for DLL In what order are locations searched to load referenced DLLs?

The dll could either be installed in the GAC or be present with the EXE in the same directory.
EDIT: The above mentioned are only just a couple of locations to resolve references.

When you add reference, you add path on your csproj on this assembly, dont you must just ensure that you can reference this dll.
When you deploy, it's another question, because your dll is copied on your Bin directory.
If you deploy you check your path of assembly in your csproj, and ensure that you deploy your assembly
Nota : check CopyLocal Property of your refrence
2 Other solution :
You can use GAC Global Assembly Cache in order to share your assemblies
Tools : Gacutil.exe in order to set assembly

Related

Avoid having to copy referenced assemblies into application directory

When deploying new builds of applications, I find that applications built by another dev would have the structure:
ApplicationName.exe
ProprietaryClassLibrary.dll
associated config files.
However, when I deploy a version I have built, I start to get "Could not load file or assembly" type errors.
These can be "resolved" by including the named assembly in the application folder. So now I would have (for example):
ApplicationName.exe
ProprietaryClassLibrary.dll
System.Data.SqlServerCe.dll (for example)
But my question is- if these aren't references I've added, and the version hasn't changed, why do I now need to include them in the application folder?
I don't necessarily want to have to include copies of libraries that are already in the GAC or installed elsewhere on the server if I don't need to- but am open to suggestions on best practice.
I have checked my the references' settings in VS to change "Copy Local", "Specific Version" as well as Path, but with limited success.
Any pointers on what might be causing this?
Thanks.

.dll's are missing after rebuild/clean-build solution

I have 3 projects in my solution and a bunch of 3rd party or company dlls. Each time I rebuild my project or clean solution, a lot of this dll's are deleted, therefore missing. It is pretty annoying to reference this dll files again and again after rebuilding. Can someone explain how to avoid this? Thanks in advance.
The bin folder is just the binary output from a build, so when you clean your solution, all the assemblies in the bin folder get deleted. You should reference the assemblies from some other location. One suggestion is to create a Shared Resources folder within your project, copy your assemblies to that folder, then reference them from that folder. This way they won't get deleted from bin on a clean/rebuild and Visual Studio will copy them there as needed.
Right-click on the References folder in your project and choose Add Reference...
Use the browse functionality to locate the assemblies you want to reference (don't worry about manually copying them to/from your bin folder)
After the reference is added, right-click on the reference in your references list and choose Properties
Make sure the Copy Local property is set to True
This will ensure that assembly is copied to your bin folder on every build.
In my case, .net framework version is the problem. I had to lower its version to 4.5 and then the projects got built properly and able to reference in other projects
As Troy explained in his answer, indeed a reference to a *.dll file, kept outside the bin folder, ensures that the dll file does not get definitively wiped out when cleanning the project.
However, just by adding a reference to the assembly might not be enough. For instance it would not work for some other file types, such as the *.pdb files as well as for the *.resources.dll files (which are typically spread in many sub-folders named after the language codes (2 letters' language code)
To depict this problem with a real life situation, I picked up an assembly for which the source code is either gone, or not compatible anymore, etc. I chose (on purpose...) a 13 years old AjaxControlToolkit composed of many component files. The picture below illustrate its composition. Every time the "Clean" command is applied to the project all these files are deleted, except the one which is the referenced assembly. Moreover having several *.resources.dll file assemblies of the same name, as in the present case, makes it inconvenient, if not possible, to add "references" to each of them from within the same project.
Nevertheless here is a pretty simple workaround:
keep this file hierarchy in a separate folder (as Troy explained in his answer)
just copy them over in the bin folder using a command line entered in the Pre-build event of the project, such as xcopy "$(SolutionDir)AjaxControlToolkit" "$(TargetDir)" /y /i /s /r /q
Hoping that will be useful to someone...

csc.exe reference external .dll file

I am trying to make a simple c# program using Growl C# API.
I tried to compile my program in two different ways:
1) I kept my .dll file in the same directory as my .cs file. Than I ran
csc /r:Growl.Connector.dll,Growl.CoreLibrary.dll /out:test.exe *.cs
It compiled fine and also ran fine.
2) Now I have created a directory inside my current working directory named growl and kept all my .dll references there.
Now when I try to compile it using the below command
csc /r:"D:\Modified\Growl_NET_Connector_SDK\libraries\growl\Growl.Connector.dll","D:
\Modified\Growl_NET_Connector_SDK\libraries\growl\Growl.CoreLibrary.dll" /out:test.exe *.cs
It compiled fine but when I tried to run it the below mentioned exception occurred.
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'Growl.Connector, Version=2.0.0.0, Culture=n
eutral, PublicKeyToken=980c2339411be384' or one of its dependencies. The system cannot find the file specified.
at GrowlNotification.Program.Main(String[] args)
So, my question is what is the correct way to reference .dll file in csc when files are in an external folder.
Here is the directory structure for 2nd case.
So, my question is what is the correct way to reference .dll file in csc when files are in an external folder.
You're already referencing them at build time. You just need to make them available at execution time too, but copying them into the same directory as the executable, when you want to run it.
You could also investigate using the Global Assembly Cache if these are signed assemblies, but personally I'd stick with just keeping the executable with the libraries on which it depends.
You can add these using the /lib and /reference command-line switches while compiling.
http://msdn.microsoft.com/en-us/library/s5bac5fx.aspx
But (Quote from the article)
An alternative to using /lib is to copy into the working directory any
required assemblies; this will allow you to simply pass the assembly
name to /reference. You can then delete the assemblies from the
working directory. Since the path to the dependent assembly is not
specified in the assembly manifest, the application can be started on
the target computer and will find and use the assembly in the global
assembly cache.
Because the compiler can reference the assembly does not imply the
common language runtime will be able to find and load the assembly at
runtime. See How the Runtime Locates Assemblies for details on how the
runtime searches for referenced assemblies.
so Jon Skeet's answer is better. (I'm just adding this to provide more info than I could in a comment, not as an answer. Jon's answer is the best IMO)
You can create symlinks to the assemblies in your libraries folder so you would only need to keep them updated in one location.

How to save DLLs in a different folder when compiling in Visual Studio?

Let's suppose I have a Window Forms / Console Application C# project with some external references and references to other class library projects in the same solution too.
When I build the Window Form project, I want the referenced libraries be stored in a different location (eg: bin\Release\Libraries), and not in the same folder as the .exe.
Is it possible to do?
There are 2 parts of your question:
How to configure solutions to build assemblies/EXE into folders of your choice - this is configured through properties of the project in VS (project properties -> build -> output path). Also value of check "copy local" property on each reference.
How to load assemblies files from non-default locations (i.e. from your ...\Libraries folder) - you need to make changes to your app.config file to add this non-default paths to assembly search location..
Link to Microsoft site no longer works, so summary from wayback machine: How to load an assembly at runtime that is located in a folder that is not the bin folder of the application:
Method 1: Install the assembly in the global assembly cache (GAC).
The GAC is a computer-wide code cache where the common language runtime is installed. The GAC stores assemblies that you specifically designate to be shared by several applications.
Note You can only install strong-named assemblies in the GAC.
Method 2: Use an application configuration (.config) file with the tags
A .config file contains the following settings:
• Settings that are specific to an application
• Settings that the common language runtime reads, such as the assembly binding policy settings and the remoting objects settings
• Settings that the application reads
The <codeBase> tags specify where the common language runtime can find an assembly. The common language runtime applies the settings of the <codeBase> tags from the .config file. The settings of the <codeBase> tags determine the version and the location of the assembly.
Method 3: Use the AssemblyResolve event
The AssemblyResolve event fires whenever the common language runtime tries to bind to an assembly and fails. You can use the AddHandler method to add an event handler to the application that returns the correct assembly whenever the AssemblyResolve event fires.
The AssemblyResolve event handler must return an [Assembly] object, and the common language runtime must bind to this object. Typically, you can use the Assembly.LoadFrom method to load the assembly and then to return the object.
Correct answers were given earlier. I'll just mention that there is a nuget package for this called PrettyBin.
Install it on your startup project. DLLs and XMLs will go to a lib folder and you'll have a working example of how it's done, if you won't to customize.
Set Reference path in project peoperties.
You can also specify where your compiled exe goes by specifying Output path in project peoperties.
You'll find best practices for organizing project references here: http://codebetter.com/patricksmacchia/2009/01/11/lessons-learned-from-the-nunit-code-base/
Look under chapter "The VisualStudio Project Reference + Copy Local true option is evil!"
Yes it is possible, you'd do it in your msbuild script. While I can't give you an exact answer, look here at this question on SO Copy all files and folders using msbuild

A problem regarding dll inheritance

I have created a dll that will be used by multiple applications, and have created an installer package that installs it to the program files, as well as adds it to the Global Assembly Cache.
The dll itself uses log4net, and requires a xml file for the logging definitions.
Therefore when the installer is run, the following files get copied to the install directory within program files:
The main dll that I developed
- The Log4Net.dll
- the Log4Net.xml file
I am now experiencing a problem. I have created a test console application for experimentation. I have added my dll as a reference, and set the 'local copy' flag to false.
When I compile the test console exe however, I noticed that it has copied the log4net.dll and log4net.xml files to the bin directory. And when running the test console, it appears that it will only work if the log4net.dll is in the same directory as the exe. This is dispite the fact that the test console application does not use log4net, only the dll that was added as a reference does.
Is there some way to have it so that the log4net.dll & xml files used will be the ones that were installed to the program files, rather than any application needed to copy over local copies? The applications that will be using my dll will not be using log4net, only the dll that they are referencing uses it.
Many thanks
Don't install into the Global Assembly Cache! Even if your library dll is used by multiple applications each should have it's own local copy. Otherwise you get into a whole world of pain for saving a few KB of disk space.
Always copy the required dlls locally. If you are really sure that the application won't need it you can simply delete the unnessesary dlls later or don't include them in the installer. But if your application will call ANY reference there it will crash at runtime. So best option is to leave them there (after all they WERE referenced for a reason).
No, it's not possible (at least not without much efford) to have .Net load dlls from arbitrary locations on the disk. And it should be this way (look up DLL-hell if you want to know why).
I suspect your problem is the configuration. You must use fully qualified names if you want it to work from the GAC. As per the documentation at http://logging.apache.org/log4net/release/faq.html:
"When loading an assembly from the GAC the fully qualified assembly name, including the version, culture and public key must be specified. This is in the standard syntax supported by System.Type.GetType. See the next FAQ on how to get the version and public key for an assembly."
I managed to resolve this by adding Log4net.dll to the GAC as well. It will now run without needing a local copy the dll.
It does however require a local copy of the XML file, to correctly log.

Categories