i have this structure
--Loader.exe
--Core.dll
--Plugins/Test.dll
--C:\Program Files\Program\Program.exe
Assembly Test.dll has reference to Core.dll which is fine. When i run Loader.exe it inject Core.dll into another process (Program.exe) and when it does it's trying to load assembly Test.dll. The problem is that Test.dll is looking for reference Core.dll in path C:\Program Files\Program\ instad of path where it was loaded.
Solution: (i'm searching)
I'm simly looking for way how to load reference from execute path instand of another's process path.
Question:
Don't understand if Core.dll loads Assembly which has reference to Core.dll why it can't load from itself ?
The directory from which referenced assemblies are loaded is determined by the configuration of the AppDomain in which your code is running in, specifically, by the AppDomain.BaseDirectory and AppDomain.RelativeSearchPath properties. By default, the assemblies are loaded from the directory which contains your entry point assembly (usually your main EXE application assembly). To customize these paths you need to create a custom AppDomain. Alternatively, you can load the assemblies manually, using Assembly.LoadFile or Assembly.LoadFrom for example.
Related
We have a .net plugin for an application that does not load a dependent library from the plugin folder.
Scenario:
Application (Revit.exe in program files) -> Loads plugin from c:\programdata\revit\plugindir\ourplugindir\<plugin.dll+dependencies>
On most machines, the load works fine. For the context of the issue, the dll dependencies are as follows
Revit.exe loads plugin.dll (revit.exe is in programfiles, plugins are in a separate predefined directory under programdata)
plugin.dll loads IdentityModel.dll (in ourplugindir directory)
IdentityModel.dll loads System.Text.Encodings.Web.DLL (in ourplugindir)
Successful probing looks like this:
IdentityModel requires System.Text.Encodings.Web.DLL
Initiate probing
Check GAC (fail)
Check root folder where Revit.exe is present (fail)
Check private sub folders where Revit.ext is present (fail)
Check ourplugindir (success)
On the machine where the plugin load fails, for some reason it does not probe ourplugindir and is hence unable to find System.Text.Encodings.Web.DLL.
The plugin dll is built using .net 4.7. The dependency is an indirect dependency.
From MSDN: https://learn.microsoft.com/en-us/dotnet/framework/deployment/how-the-runtime-locates-assemblies
Assembly location can also be determined using the current binding
context. This most often occurs when the Assembly.LoadFrom method is
used and in COM interop scenarios. If an assembly uses the LoadFrom
method to reference another assembly, the calling assembly's location
is considered to be a hint about where to find the referenced
assembly.
Since the plugins are dynamically loaded by Revit.exe, I can only assume that the application uses Assembly.LoadFrom or something similar to load the plugins.
So the question is, why does the runtime correctly probe and find the dependent dll in the plugin folder on some machines while it doesn't probe the same folder on other machines?
Have you tried using an assembly resolver?
I'm trying to make a tool similar to Unity (obviously at a lower scale) and I need to be able to compile scripts which work in both the editor and the final game.
My approach to that is compiling the code in the editor using the ReferencedAssembly of my game executable, while the game executable already contains all the scripts which are present in compile time.
However I'm having a problem with the editor part. Basically I set
parameters.ReferencedAssemblies.Add ("path/to/Game.exe");
parameters.GenerateInMemory=true;
parameters.GenerateExecutable=false;
and then compile. There are no compilation errors but when trying to use
var typeArray=results.CompiledAssembly.GetTypes();
a ReflectionTypeLoadException exception is thrown:
Could not load file or assembly 'Game, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies.
However, copying my executable Game.exe to the tool's directory, and changing the reference assembly to
parameters.ReferencedAssemblies.Add ("Game.exe");
allows me to compile and access to GetTypes without errors.
So, my questions are:
a) how can I make GetTypes work when using an assembly which is in another directory? (note: I'd rather not add the path to the GAC, as it should be a generic tool)
b) would it be possible to access type info without loading the referenced assembly? I mean, in NET 4.5 Type and TypeInfo are supposed to be splitted just for this reason, isn't it?
Regarding your point a): "how can I make GetTypes work when using an assembly which is in another directory?
I think you could you use Assembly.LoadFrom Method (String) to load the assembly from another directory.
Regarding your point b): "would it be possible to access type info without loading the referenced assembly?"
I'm not sure you'd be able to access type info without loading it in some fashion, but are you aware of loading Assemblies into the Reflection-Only Context?
The reflection-only load context allows you to examine assemblies compiled for other platforms or for other versions of the .NET Framework. Code loaded into this context can only be examined; it cannot be executed. This means that objects cannot be created, because constructors cannot be executed. Because the code cannot be executed, dependencies are not automatically loaded. If you need to examine them, you must load them yourself.
On a second reading of your question, how does "game.exe" get referenced in your project file?
If it's a case of MSBuild needing to copy it to the build output folder of the project, you could add "game.exe as an item in the project, set the build action to "None" and the Copy to Output Directory Property to "Copy if newer".
I have the following simple folder structure:
Root
Root\Executable.exe
Root\Subfolder
Root\Subfolder\Control.dll
Root\Subfolder\ControlDependency.dll
The subfolder has a control based on a 3rd party library. I expected the control to load its dependencies from its own folder but instead it is looking for dependencies in the executable folder.
Is this normal and why it is happening?
When you build the project, all the referenced assemblies will be copied in the output folder and then referenced.
The .NET CLR follows these steps to assembly resolving:
Examine the Configuration Files
Check for Previously Referenced Assemblies
Check the Global Assembly Cache
Locate the Assembly through Codebases or Probing
If you need to load an assembly at runtime which can be located in any folder (not only the bin folder of the application) you can use one of these three methods:
Install the assembly into the Global Assembly Cache (GAC)
Use an application configuration (.config) file with the
tag.
Use the AssemblyResolve event
Please, follow this links to learn more:
http://msdn.microsoft.com/en-us/library/yx7xezcf.aspx
http://support.microsoft.com/kb/837908/it
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.
here's my scenario:
I have three projects: two DLLs and one console application, let's name them foo.dll, bar.dll and console.exe. Console.exe loads foo.dll using Assembly.LoadFile(#"c:\foo.dll"). Foo.dll's project has a reference to bar.dll and makes use of a class. Console.exe loads foo.dll fine, the problem occurs when foo.dll tries to use bar.dll's class. I get a "could not load assembly: "bar.dll" blah blah exception.
Some points:
All projects are strong named
Would prefer to not use the GAC
Bar.dll is in c:\bar.dll
So everything is in the same local directory, the correct dlls are being referenced (via project properties, and I've used Reflector to make sure the assembly versions are correct). If I install bar.dll to the GAC everything works as expected.
I think it has something to do with the Assembly.LoadFile call, and making a hop to the second DLL, but I'm not sure.
Thanks for your time and input.
Assembly.LoadFile() should only ever be used in very special circumstances. The assembly doesn't have a loading context, that's why bar.dll cannot be found. The only real use case is tooling, programs that dump assembly metadata.
Use Load or LoadFrom(). Troubleshoot problems with fuslogvw.exe