I have a C# application to load custom configuration section from assembly in different folder.
For example:
AppBase: C:\Code
Assembly Folder: C:\Lib\My.Core.dll
I have error says "System can't find specific file". I understand it is caused by different folder. Can I reference it in absolute path?
Here is my config file:
<section name="regional" type="My.Core.RegionalSection, My.Core" />
Can I make it something like
<section name="regional" type="My.Core.RegionalSection, C:\Lib\My.Core" />
No, you cannot specify a path in a type description. The CLR looks for assemblies in the GAC or the directory that contains the startup EXE. You can let it look in subdirectories by using the <probing> element in your .config file. Other paths that are completely unrelated to the startup EXE directory requires implementing the AppDomain.AssemblyResolve event.
Deploying DLLs in the same directory as the EXE is a wise thing to do. It avoids DLL Hell.
Related
I register my assemblies by autofac in configuration.
I want the autofac load assemblies from another folder, no 'bin' folder.
I try put it 'type' attribute path of asssembly like this:
<component type="Amazon.SQS.AmazonSQSClient, amazonDlls/AWSSDK" service="Amazon.SQS.IAmazonSQS, AWSSDK" />
But I get error of invalid assembly name.
How can I do it - register assembly from specific folder?
by the way: I know it is possible from code but I want from config.
It is not possible to provide a path to the assembly in the fully-qualified type name. It seems it's not even possible to register types from libraries not located in different directory than "bin" folder. Even if you prepare configuration file in the same folder as dll you want to register and read it this way:
builder.RegisterModule(new ConfigurationSettinsgReader("<section-name>", "amazonDlls/app.config"));
you will get the exception of type not found.
As noted in the documentation the names of component types are fully-qualified type names, which is a format defined by the .NET specification. A fully-qualified type name does not include a path.
Specifying a path is not possible with the out-of-the-box configuration format. You have a couple of options.
Option 1: Add a Probing Path
By default, .NET only searches the bin folder of your application for assemblies. You can read about how .NET locates assemblies on MSDN
.NET does allow you to specify additional paths to search via app.config or web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;bin\plugins" />
</assemblyBinding>
</runtime>
<configuration>
These paths must be subdirectories of the bin folder so that may not work for you.
If it must be outside the bin folder (and not under it in a subdirectory) you can use the <codeBase> element to specify a URL location. If you do that, it looks like the assembly must have a strong name, so keep that in mind. The probingPath mechanism won't require the strong name.
And, of course, there are risks inherent with loading assemblies that are in specified locations outside the GAC and outside your bin folder. Stuff to consider.
Option 2: Create Your Own Configuration Reader
This will be a lot harder. You can grab the Autofac.Configuration source and create your own version of the configuration reader that includes file location support. You'll probably need to look at Assembly.LoadFrom to get that to work, but, again, there are some risks doing that. The Assembly.LoadFrom docs outline the issues.
I built a simple WIX installer that deploys an exe and a third-party dll, and creates shortcuts. The installer appears to work fine, and places both the exe and dll in a folder in C:\Program Files(x86), but when I try to run the application I get an error:
System.IO.FileLoadException: Could not load file or assembly 'GACManagerApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'GACManagerApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
The application runs just fine from the IDE, and even from the executable in the IDE bin directory, but after deploying with WIX cannot load the assembly. On a hunch, I copied the dll from the bin directory to the deployed location, and it started working. Looking closer, it appears that WIX is doing something to the third-party metadata when it deploys that changes the signature enough that the exe can no longer load it. Here is the definition of the assembly in the wxs:
<Component Id="GACManagerApi">
<File Id="GACManagerApiDLL" Name="GACManagerApi.dll" Source="$(var.GHCComponentManager.TargetPath)" />
</Component>
I also noticed that the details on the dll properties are different, with the File description, product name and original filename being changed to that of my executable, instead of the original values for the assembly.
Am I missing something in my wsx that is causing this to happen?
I figured it out. The problem was how I was defining the Source attribute. The hint really should have been in the file property details, but I was too consumed with my assumptions to see it. I was reading some other documents talking about pulling assemblies from outside the project when I noticed it.
I was defining the source as:
Source="$(var.GHCComponentManager.TargetPath)"
which translates literally to the full path of my release executable. With the Name attribute of the File element, it was effectively moving my executable to the release location and renaming it GACManagerApi.dll. The correct source should be:
Source="$(var.GHCComponentManager.TargetDir)\GACManagerApi.dll"
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 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>
Typically we keep our config values in web.config/app.config and for the environment global config varialbes (and not application specific) in server machine.config file.
When deploying an object to the GAC where is the best location to keep these config type values? It seems that the best location would be a linked resource file.
Does anyone have any experience/recommendation with this approach? (sample code?)
thx
The configuration values need to be in the application configuration of the executing assembly. It is the responsibility of the application to have the configuration values so that your assembly will have access to them when it is loaded into the AppDomain.
I've had a need for assembly-specific config files (as opposed to executing assembly config files) in the past.
For an assembly in the GAC, it is possible (but not recommended) to physically copy a config file to the assembly dll folder.
The solution I've used for creating a config file that can be shared across assemblies regardless of AppDomain is a a simple registry entry for my application that defines a shared config file location. This way, any assembly can retrieve configuration settings from a shared location, regardless of which executing assembly launched it. (especially useful for scripting - otherwise, you'd have to deploy a config file named wscript.exe.config in the windows\system32 folder - UGH!)
if you dont care of having specific configuration for each application using your dll you can place the configuration in the machine.config file inside the framework folder.
%systemRoot%/Windows/Microsoft.Net/Framework/[Version]/Machine.config