.net-assembly resolution - c#

I am studying about assemblies and confused on some points after searching I am asking question here. I read about assembly resolution that for strongly named assemblies the order of assembly resolution is to first check GAC then the root directory and then private probing.
Suppose I have a solution with multiple projects and within this there is a folder to place all the reference assemblies lets say log4net and in project where I need to use log4net assembly I add reference of log4net dll pointing to the folder within application solution directory where all referenced dlls have been placed. So why CLR check GAC and then root directory etc why not from the path mentioned while adding reference.

I think you mean "in Visual Studio" when you say "add reference to this".
What will happen when you run the program on a machine where this path does not exist?
Btw. the "Add reference" in visual studio is only used at compile time. It will copy the referenced dll to the target folder.
Visual Studio creates a target folder (Standard bin\Debug or bin\Release) in the project folder and stores there all files (exe, dll, config) for deployment.
Installing DLLs into GAC has to be done manually and makes sense only if it is a DLL which is used by several applications and should be used carefully.
You could get strange and difficult to find errors when your application loads a dll from GAC and this dll has another version as expected by your application.

Related

errors CS0246, CS1504 and CS2015 when trying to compile through csc [duplicate]

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 deploy a dependent DLL when a client solution references my project?

I have a C# project which builds a library DLL, myLib.dll. This DLL has a dependency on a 3rd party DLL, dep.dll (which I provide but do not build).
I want others to be able to use my library by adding my project to their solutions and referencing it. Adding my project as a reference automatically copies myLib.dll to the Target directory of their app, but of course dep.dll is not copied with it.
Bear in mind that I have no control over where my project is in their code tree, and the DLL can't know where it was copied from.
The only solution I can see is to force the user to add a build event which copies dep.dll to their target directory. We can't assume users can create environment variables.
This is very undesirable for several reasons (it's not really one dependency - I simplified things, I don't want them to have to be concerned about the dependencies in my project, and it's very fragile - adding an extra dependent DLL to my project would require everyone to update their build scripts).
I can't load the dep.dll directly as I don't know where it is - my build scripts can copy it to the same target directory as myLib.dll but the actual version of myLib.dll they run will have been copied somewhere else.
I also can't make dep.dll a reference directly (probably because it's not a .NET assembly). I just get "Error loading code-completion information for dep from dep.DLL. Format of the executable (.exe) or library (.dll) is invalid".
So is there any way to have the dependent DLL just seamlessly copied with myLib.dll when a client builds their application? [I'm using Sharp Develop if it matters.]
Can you add dep.dll to your projects root folder as a file like a .cs file. Set the Build Action to None and Copy to Output Directory to Copy if newer.

Does adding a reference in a C# / VisualStudio project import the library or simply reference it?

I need to use an external DLL library within my project. When I add the reference to that library, is my project importing it, or is it just referencing the DLL at its location?
At compile time, it is a reference to the dll at that location. However once compilation is done, the referenced assemblies may be copied to output directory of your project i.e. next to your project's dll or exe e.g. bin\Release (configurable). You can control this behavior by changing the "Copy Local" property on the reference.
At run time, the assembly is searched for in multiple places such as; the same directory where your primary executable/assembly is placed. See Locating the Assembly through probing for details.
.NET does not embed the referenced assembly in your exe/dll unless you use ILMerge.
Define what you mean by "import"? Where you think it is imported to? It is a reference. The file gets copied to the output when the reference is told to do that.
When I reference DLLs from outside of my project, I have found that the dll file gets copied into by bin/Debug or bin/Release folder. Then, links are resolved at runtime, so while by .exe can be moved around, I still need those DLLs in my path or else I get a "missing reference" error.
This has bitten me a few time when running a C# project via mono on a Linux distribution until I remembered to copy the .dll files over as well. Then it worked fine.

How can I load assemblies that are placed in the project (portable class library) folder?

I have a .dll file in my project folder and would like to load it via Assembly.Load().
AssemblyName name = new AssemblyName("Portable.Store, Version=0.1.0.0, Culture=neutral, PublicKeyToken=12ay62c33eocf6uf");
Assembly assembly = Assembly.Load(name);
However this would throw a FileNotFoundException due to not specifying a path. And I am unable to use Assembly.LoadFrom() or Assembly.LoadFile() because Portable Class Libraries only support Assembly.Load()
Is there a way to do this inside a pcl? Any help is appreciated, thank you!
Edit #1: Would it matter if the assembly I'm trying to load is a non PCL? I know that this defeats the purpose of the PCL however there are a few libraries that are not included in the PCL. Therefore using conditional compilation, depending on the platform, I will load platform specific assemblies.
Edit #2: Found some more information on where the dll should be placed: https://stackoverflow.com/a/6440406/2464165
As of now I just placed it inside my project folder, with the .sln file and what not Where exactly would be the app probing path?
Edit #3: I was able to get my dll file placed inside the Resources Folder of a .dll file. So I have MyPCL.dll and inside that is where I have the ResourcesFolder/Portable.Store. How could I tell the Assembly.Load to look in specific folders instead of just the main AppX root directory?
I'm making the assumption that you are running the portable library in a Windows Store application (based on the assembly name you are trying to load).
There are two places that store apps find their assemblies, either in GAC if it is a framework assembly or the Appx package if it is a user assembly.
As "Portable.Store" (which I assuming is from my PclContrib project) is a user assembly, it must be loaded from the AppX package. To ensure that both assemblies end up in the AppX package, simply make sure that the Windows Store project containing the AppxManifest references both of them. That's it.
If Assembly.Load still cannot find the assembly, check to make sure that the strong name you are passing to Assembly.Load is correct.

Setting folder for dependencies in C#/.NET

I have a C# project with a bunch of dependencies, but I want to store them in another folder from where the executable is.
For example
WTEngine/
/bin
--Dependencies go here
/otherfolder
WTEngine.exe
How do I do that? I move them and the executable can't find them anymore
This answer for ASP.NET addresses the same issue, and most of the answers can be effectively ported to a desktop executable: How do I reference assemblies outside the bin folder in an ASP.net application?
Also see How do I change the lookup path for .NET libraries referenced via #using in Managed C++?
The .NET dependencies are loaded automatically from two places:
GAC (http://en.wikipedia.org/wiki/Global_Assembly_Cache)
the current path of the executing assembly (your exe)
You cannot move the dependencies in another folder and have them loaded automatically.
If you decide to load the assemblies manually, check out this question:
How to Load an Assembly to AppDomain with all references recursively?

Categories

Resources