I have a console application (NGameHost) running in a specific directory (C:\Program Files\NetworkGame3\api\). It uses the files available in that directory and the console application works well when run on its own. It also exposes various methods that use the DLLs (and other files such as config files) from that directory. I now have another console application (located elsewhere) that tried to call those methods and return the results. I've set Copy Local: False so that it executes within that directory instead of creating a local version. However I get the error "Could not load file or assembly ... or one of its dependencies. The system cannot find the file specified."
How can I call the methods from a console application located in another directory?
When you set copy local = false what you're saying is that do not copy the assembly to the local directory in which case assembly will available in one of the places where the runtime looks for it.
See How the runtime locates assembly
Your assembly has to be either in GAC or in one of the probing locations.
You can use the GAC, a config approach or an assembly resolve event.
This KB covers it in more detail:
http://support.microsoft.com/kb/837908
Also look into probing paths:
http://msdn.microsoft.com/en-us/library/15hyw9x3(v=vs.71).aspx
I've recently been bashing my head against a brick wall trying to resolve a very similar problem. I've a DLL I want to load at runtime, and it has it's own dependencies. I couldn't for the life of me figure out why it would load, but when calling a class's constructor in the loaded assembly, that no error was raised, and execution simply stalls, leaving you wondering what's going on.
Turns out that a dependency of the loaded assembly was in a different .NET version, and there is an App.Config on that code to enable mixed mode assemblies. So I naturally had to bring that into my code too, as I'm calling an assembly that calls an assembly in a different version of .NET.
The error didn't present itself until I copied all the dependent's DLL's to my application in development. Now I can remove them again! In doing so, I get a DLL Loader Lock warning message. If I suppress it or ignore it, my code works.
In my case then, the resolution was :
<?xml version="1.0"?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0"/>
</startup>
</configuration>
Related
I am currently working on a project which requires the use of a custom dll for authentication.
This dll is registered (so they told me) in the GAC of both the Production and Test environments.
The company policies state that you "shouldn't include the dll reference in your application's web.config file", that is, you shouldn't have something like :
<add assembly="" ....="" mydll=""> etc.
in your web.config, at least for this dll I am talking about. They say, since it's registered in the GAC, the application will load it anyway.
The problem is , if you don't add the assemby reference in your web .config , the application is not going to find it , no matter what they say.
Since I am sure the dll is actually registered in the GAC, my question is :
shouldn't the application be able to load the dll anyway , no matter if you add the reference in the web.config or not ?
I was convinced that, adding the reference to the project, the dll 's GAC location would be stored in the application's assembly so that the application itself would be able to find the assembly in the GAC , no matter what the working system is , given that the dll is actually registered in the working system's GAC .
But I must be wrong.
What is the real way it works ?
I tried deleting the <add assembly ...> entry from the web.config : I have a runtime error everytime I reference a method in the dll , in my test environment ; same thing happens in the Production environment;
shouldn't the application be able to load the dll anyway , no matter if you add the reference in the web.config or not ?
By the logic applications would load every assembly in the GAC when they start up, could you imagine how slow that would be? No, that's not how it works.
When you reference a DLL locally in your project, all you are doing is adding it into the manifest which tells the application to load it as part of your application. When the CLR loads, it would first of all check if there is an equivalent version of your DLL in the GAC, if one exists it will load that version, if not it would attempt to load the local version.
See How the Runtime Locates Assemblies
I have a Referenced Assembly where CopyLocal = True, The file is present in the bin folder, but it is not being copied to Temporary ASP.NET Files when I run the solution from Visual Studio
The error message is the usual:
An error occurred loading a configuration file: Could not load file or assembly 'MyNamespace.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Solution / Actual Cause
There were a number of problems:
Problem 1: In order to load a configProtectedData Provider, at least in my environment - the assembly must be in the GAC.
The reason for this was revealed by the fusion logs. Although my web app could locate the assembly in the bin folder - the web server (IIS Express) also needs to load it and it was this part that was failing. Since the web server has no knowledge of my bin folder, the only place it can possibly get the file from is the GAC. Fusion shows that IIS Express was having-a-go at looking in Temp ASP .Net folders but I think that this might be some kind of fallback and in my case the shadow copy was indeed copying the assembly but to a different location (Temporary ASP.NET Files\root\4f27e88a\bfcf2f79\assembly\dl3\06324d99\85ff3c73_1943cf01) that IIS Express didn't know to look for.
Problem 2: Once I had the assembly in the GAC properly, (surprise) Typo. I had the class name wrong in the "type" attribute
The thought process to get to the Solution
First: Follow Ivan Niktin's debugging process, Second Fusion Logs are your friend
It makes sense that it is trying to load it from Temporary ASP.Net Files as this is an MVC Web Application.
What doesn't makes sense is that the Temporary ASP.Net Files location that is being searched is empty. If I add the assembly to the GAC then it loads fine, but this is not an option for my deployment scenario.
The Fusion Log shows as the first path searched:
LOG: Attempting download of new URL file:
///C:/Users/Rob/AppData/Local/Temp/Temporary ASP.NET Files/root
/4f27e88a/bfcf2f79/MyNamespace.Configuration.DLL
The other paths are:
.../MyNamespace.Configuration.DLL
.../MyNamespace.Configuration/MyNamespace.Configuration.DLL
.../MyNamespace.Configuration.EXE
.../MyNamespace.Configuration/MyNamespace.Configuration.EXE
When I view the content of the folder that is being searched for the DLL - It is empty!
There is only one namespace involved MyNamespace.Configuration - this is a new / nearly empty assembly with no dependencies other than System.Configuration in the GAC, the host project and referenced assembly are both using .Net Framework 4.0
The part of the application that is trying to load the affected assembly is:
<configProtectedData defaultProvider="DynamicFileConfigurationProvider">
<providers>
<add name="DynamicFileConfigurationProvider"
type="MyNamespace.Configuration.DynamicFileConfigurationProvider,
MyNamespace.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=aeecd94c462a579a"
SelectorKeyProviderName="HostNameSelectorKeyProvider"/>
</providers>
</configProtectedData>
Update:
Setting shadowCopyBinAssemblies to false had the effect of causing the binder to look at ../Microsoft.NET/Framework/v4.0.30319/Temporary ASP.NET Files/... Rather than the previous IIS Express location
Intercepting the exception earlier did not provide any additional information, simply the same message that the file could not be found.
Referencing the assembly in another host, both console and web turned up no info, the assembly loads fine and the methods can be called.
Manually placing the assembly in the location in which the binder is looking for it also works - It seems to me that the assembly binder is looking in the wrong place. i.e. if shadowCopyBinAssemblies is false, then it should only look in the bin folder. if shadowCopyBinAssemblies is true then the shadow copy location should have my app's dll's as well as any that it references - it shouldn't be empty.
Basically, Temporary ASP.NET Files folder contains assembly copies to allow file updates in the bin folder. When the runtime loads an assembly, it becomes locked and thus you cannot update your assemblies on the server. To solve the problem, the runtime copies them into the "Temporary ASP.NET Files" folder.
I'd try to tackle the problem as following:
Try to disable show copying (<hostingEnvironment shadowCopyBinAssemblies="false" /> or http://msdn.microsoft.com/en-us/library/system.appdomainsetup.shadowcopyfiles.aspx) to check if the problem really relates to Temporary ASP.NET Files.
Try to get more details about the exception using "Break on exception" feature in VS or by using an exception handler. Check exception.Data and .FusionLog properties for more detailed information about the exception.
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler((x, y) =>
{
var exception = y.ExceptionObject as System.IO.FileNotFoundException;
if (exception != null)
// Retrieve exception information here
});
Try to load the problematic assembly in a separate project. Even a simple console app will be fine.
These activities will allow you to narrow cause of the problem.
Not sure about the cause in MVC application, but I encountered a similar kind of issue in my web form based web application where Referenced Assembly where we set to CopyLocal = True. My web project was referencing assemblies both from the GAC and a folder located in the relative path inside the solution.
I resolved the issue by
Removing all the assemblies that were referenced form the relative path
Manually deleted the debug and release folders in both bin and obj folders for all projects.
Added back the assemblies from the local path.
Re-build the project
And things started working. You should probably try these steps as well and this might help resolve the issue.
MS VS C# 2012
I develope an application that uses MEF to interconnect several binary assemblies loaded from a database. One of its separate plug-in assemblies has dependency on a third party DLL that cannot be included in the main application. When I include that third party dll in the main application's references (plug-in has the reference too), compile and run it then the application runs smoothly. But when I remove that DLL from the main application's references (I do not need it there actually, I need to reference it in the plug-in's project only) and use AppDomain.CurrentDomain.AssemblyResolve event to load the third party DLL assembly from database then it runs OK, but later, at runtime, when the plug-in tries to use a XXX type (located in that third party assembly) the application raises an exception, complaining it cannot find the XXX type in the main assembly. I'm stuck.
Does anyone know what could cause that? Any sane explanation would be very appreciated.
Though I would love to see an even better approach, my team on a project where MEF was used decided to have the other projects that referenced third party assemblies each perform a post build event like so:
xcopy /Y /I /D "$(TargetDir)*.*" "$(SolutionDir)YourMainProjectNameHere\Bin\$(ConfigurationName)\"
For this to work, of course, said third party references in the other projects need to be set to "Copy Local" as well.
The assembly resovler search for the dll in it's probing domains. which is by default GAC and Private Bin folder. So if you don't want to keep third party dlls in your main application's bin folder then Either you can install those third party dlls into GAC. Or if you have a specific locations where those dlls could be found then add that path to the probing domin.
Just put this line in your configuration file.
<!-- Adding custom folder of the Private bin to default probing domains -->
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="c:\plugins;"/>
</assemblyBinding>
</runtime>
Alternative you can use Directory catalog and specify a location where the third party dlls are placed.
var catalog = new AggregateCatalog(
new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()),
new DirectoryCatalog("Extensions"));
How can I dynamically load a DLL?
Please don't suggest:
Don't suggest GAC, because the DLL is already made and can't be changed or updated.
Don't suggest hintpath, Assembly.LoadFrom(...) since this functionality works at debugging not outside the project.
If I copy that DLL/exe onto a test machine outside the project then it shows an error: could not load .dll.
I also asked a question at the MSDN forums.
Could anyone help me?
Thanks
Ashish
System.Reflection.Assembly.LoadFile() works just fine for this.
If you are getting BadImageFormatException, check whether the assembly you are trying to load is compiled for the same platform target (x86 or x64) as the assembly doing the loading.
Update based on comments
Sounds like you are trying to load a .NET 2.0 assembly into a .NET 4.0 application, and you have already put the following in your application configuration file:
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" />
</startup>
</configuration>
In that case, check to make sure your configuration file is getting deployed on your target machine alongside your executable. For example, if your application is called MyProgram.exe, your configuration file should be called MyProgram.exe.config - and it needs to be copied to the same folder as the executable on your target machine to have any effect - the framework will load this file when it starts up, if it exists.
1) Try using assembly.loadfile function instead of loadfrom. It will work outside the project also. 2) If u got assembly mixed mode error then, just need to copy xml file along with dll generated in bin folder.xml file contains app.config file data. Code in app.config file is...
also check link... http://social.msdn.microsoft.com/Forums/en/csharpide/thread/99691cc4-27df-48e7-b4aa-377f74109425
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.