Could not load file or assembly 'Microsoft.Practices.Unity.Configuration

May 7, 2008 at 3:02 PM
Hi,

I am getting the error
"An error occurred creating the configuration section handler for unity: Could not load file or assembly 'Microsoft.Practices.Unity.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified. (C:\Projects\bin\MyFile.config line 4)"

The config file is
---
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</configSections>
<unity>
<containers>
---

code used is

ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = "C:\Projects\bin\MyFile.config";
System.Configuration.Configuration config
= ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
UnityConfigurationSection section = new UnityConfigurationSection();
ConfigurationSection cs = config.GetSection("unity");

The last line gives error.
May 7, 2008 at 11:25 PM
I have a few questions for you.

  1. Do you have a reference to Microsoft.Practices.Unity.Configuration.dll ? I would think so since code wouldn't compile.
  2. Are attempting to run this from a unit test or somewhere else where your application base (ie working directory) would be different than C:\Projects\bin ?
  3. Is Microsoft.Practices.Unity.Configuration.dll in C:\Projects\bin ?


sanchaykulkarni wrote:
Hi,

I am getting the error
"An error occurred creating the configuration section handler for unity: Could not load file or assembly 'Microsoft.Practices.Unity.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified. (C:\Projects\bin\MyFile.config line 4)"

The config file is
---
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</configSections>
<unity>
<containers>
---

code used is

ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = "C:\Projects\bin\MyFile.config";
System.Configuration.Configuration config
= ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
UnityConfigurationSection section = new UnityConfigurationSection();
ConfigurationSection cs = config.GetSection("unity");

The last line gives error.

May 8, 2008 at 12:05 AM
Hello,

I tried this code and it worked

ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = "MyFile.config";
System.Configuration.Configuration config
= ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
UnityConfigurationSection cs = (UnityConfigurationSection) config.GetSection("unity");
 

Cheers
Yaz
May 8, 2008 at 6:49 AM
pbolduc :

1. Do you have a reference to Microsoft.Practices.Unity.Configuration.dll ? I would think so since code wouldn't compile.
Yes, Microsoft.Practices.Unity.Configuration.dll, Microsoft.Practices.ObjectBuilder2.dll, Microsoft.Practices.Unity.dll are referred in the project.
2. Are attempting to run this from a unit test or somewhere else where your application base (ie working directory) would be different than C:\Projects\bin ?
Working directory is same.
3. Is Microsoft.Practices.Unity.Configuration.dll in C:\Projects\bin ?
All the 3 files along with the config file are in the above folder.

---------
Yaz:

ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = "MyFile.config";//This line of code can't find the file "MyFile.config", as the current dir. is by default set to "MyDocuments" folder.
System.Configuration.Configuration config
= ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
UnityConfigurationSection cs = (UnityConfigurationSection) config.GetSection("unity");
May 8, 2008 at 9:06 AM
Edited May 8, 2008 at 9:29 AM
Hello,

I have tried with the full path and it works for me, one question for you. Is the DLL that runs the code in C:\projects\bin folder?

Cheers
Yaz
May 8, 2008 at 9:52 AM
Edited May 8, 2008 at 9:53 AM
Yes, it is there. Default project output is not changed, hence its in C:\Projects\bin folder.

Another thought:
As per my knowledge, Unity assemblies need not be put into the GAC, as long as they are available in the execution folder. So is this related to GAC in any way?
May 8, 2008 at 10:49 AM
I do not have the Unity assemblies in the GAC and it works for me.

Sorry that I am going to ask you some silly questions.

You have a test project or console application and some code and MyFile.config. In the properties for the MyFile.config file, you have Copy to output directory, is this set to Copy always?

Cheers
Yaz
May 8, 2008 at 11:31 AM
Edited May 8, 2008 at 12:00 PM
Yes, the settings are same as mentioned above.
I even tried deleting all Unity dlls and config file from bin folder, and they were again copied when I executed the appilcation.

There is something else tricky here!!!!

UPDATE:
I created a new console application, and its working there!!!!!!!!

I am confused.
Jun 25, 2008 at 3:07 PM
Are attempting to run this from a unit test or somewhere else where your application?

I am getting the error 
"System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Practices.Unity, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. Le fichier spécifié est introuvable.=== Pre-bind state information ==="
knowing that it was an execution unit testing.
What is the problem.
Best regards
Jun 26, 2008 at 4:58 AM
MS Excel VBA is calling a .Net Assembly (DLL-1), and this assembly is calling another .Net Assembly (DLL-2). DLL-2 is referring to Unity dlls.

When System.Configuration.Configuration reads the unity config file, it tries to locate the unity DLLs in the same folder where the Excel.EXE is located!!!! I verified this by copying the 3 DLLs in Excel.EXE foler, and its working fine.

Microsoft.Practices.ObjectBuilder2.dll
Microsoft.Practices.Unity.Configuration.dll
Microsoft.Practices.Unity.dll

BUT THIS IS NOT A GOOD AND VALID SOLUTON, something better must be done for the same.


Jun 26, 2008 at 5:54 AM
Can you run fuslogvw and look at everywhere Excel is trying to load the assemblies from? There may be some more information available there.

A sledgehammer solution would be to put the Unity assemblies in the GAC; it should look there first.

Otherwise, if we can't get your VBA & excel to behave, you could use OpenMappedExe to manually specify where the configuration file is.



Jun 26, 2008 at 6:24 AM

Running FUSLOGVW would certainly be a great step to figuring out what's being loaded where. The following blog post has some pointers as to how to do this.

http://www.ademiller.com/blogs/tech/2008/01/gotchas-fusion-log-viewer-your-best-friend-for-assembly-load-errors/

If you configure FUSLOGVW and rerun your application you'll be able to see the failed assembly loads and the probing path that the loader tried to use and the AppDomain root.

Second could you give us more details into what your application actually looks like. The whole VBA thing came as a bit of a surprise :). Where are you executing the ExeConfigurationFileMap code? One of the DLLs in your Projects\bin folder right? Which version of .NET and Excel are you using etc?

In the meantime I'll try and repro based on the info I have.

Ade
Microsoft p&p
http://www.ademiller.com/tech/

Jun 26, 2008 at 7:02 AM
So I'm guessing you'll see something like this below. As various people have speculated the AppBase is set to that EXCEL folder. This is actually he behavior I'd expect. Out of interest why are you using this approach. Have you considered creating a VSTO solution and then calling back into your VBA code. I suspect this is a better supported scenario although I'll follow up with the VBA/VSTO team and see what they say.
.




























*** Assembly Binder Log Entry (6/25/2008 @ 10:48:56 PM) *** The operation failed. Bind result: hr = 0x80070002. The system cannot find the file specified. Assembly manager loaded from: c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll Running under executable C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE --- A detailed error log follows. === Pre-bind state information === LOG: User = Ade LOG: DisplayName = Microsoft.Practices.Unity.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 (Fully-specified) LOG: Appbase = file:///C:/Program Files/Microsoft Office/OFFICE11/ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = EXCEL.EXE Calling assembly : System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a. === LOG: Start binding of native image Microsoft.Practices.Unity.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35. WRN: No matching native image found. 
Jun 26, 2008 at 5:59 PM
So I've thought about this some more and this behavior is actually by design and nothing to do with Excel, VBA or Unity for that matter.
This will occur in any case where you have an unmanaged application calling a .NET assembly. A CCW gets created and this
try and load assemblies from either the GAC or the domain's AppBase (which is the directory containing the unmanaged
EXE).

I would seriously consider VSTO as this is one of the key issues it solves as the AppBase for a VSTO customization is the document
folder not the application folder (of EXCEL.EXE). I realize that VSTO may not be an option for you but I'd like to understand why.

Putting stuff in the GAC would work but you will have to do this for each assembly your application loads, not just Unity but all the
other assemblies of types your DI container refers to. There are some other options but I'd like to explore the VSTO one first.
Jun 27, 2008 at 7:31 AM
VSTO vs VBA

We started using VSTO (2005) for the same, it was the obvious choice. But we ran into problems, one of the major problem was, while deploying the
custom menu was not consistently displayed in Excel. We can't move to VSTO-2008 right now, I am not sure if this Menu display problem is fixed in VSTO-2008,
but anyways thats a diff. topic.

Summary for findings/problems for the "Could not load file or assembly" error...
1)Using the "OpenMappedExeConfiguration", opened the Configuration file, the System.Configuration.Configuration can locate and open the file, but
when it starts reading the "<configSections>" , it can't load the DLL, Unity DLLs in this case.
2)Registered the DLLs in GAC, (verifed that version is correct in GAC and in config file), still DLLs can't be loaded.
3)you are right, the problem is not related to Unity, it can't find any DLLs.

I will try diff. the GAC options e.g tyr registering diff. DLL versions in GAC , and check whether this fixes the issue.

By the way, what's the reason it for this CCW behavior? (NOTE: This is working in CastleWindsor Framework)


Jun 27, 2008 at 6:47 PM
I'm not fully upto speed on VSTO any more although you might want to follow up on the VSTO forum on MSDN.

#1 is the behavior I'd expect. Did you look in the fusion log to see where it was trying to load the assemblies from? I'm very
surprised that registering in the GAC did not fix the issue - although I'm not recommending this approach as you will have to
place all your DLLs in the GAC to get this to work. Again the fusion log will show you exactly why it's not loading the DLLs.
I tried this on my machine and adding Microsoft.Practices.Unity.Configuration.DLL to the GAC causes the call(s) to
OpenMappedExeConfiguration to succeed. Note: Their is an issue with running GACUTIL as a non-Admin on Vista with
VS 2005 see here for details.

I'm very surprised you see a different behavior with Castle Windsor. Where are these DLLs installed? What does the fusion
log viewer tell you about how these DLLs got loaded?

The CCW behavior is really no different from the default .NET behavior when you create and .NET AppDomain. Unless you
explicitly set the AppBase on the domain it will be the folder that the EXE is in. So assemblies can be loaded from the AppBase
folder or sub folders or (if they are fully trusted) from the GAC. This is part of the .NET security model.

Your other option here would be to modify the AppDomain load behavior from within your application by implementing 
AppDomain.AssemblyResolve event. This fires when the AppDomain cannot load an assembly and gives the event handler an
opportunity to provide the assembly. You can effectively extend the assembly probing path this. You can find an example in
the WSSF:ME source code. This is a lot of code but you actually only need three self contained classes from the source.

AssemblyLoader

AssemblyResolver

ReflectionHelper

Your code then just calls before trying to load the configuration

 

AssemblyLoader.LoadAll(@"c:\Projects\...");

 

You'll have to make a minor alteration to the code as the version that's shipped adds "\lib" to the passed in path and remove
the calls to to the methods on the Guard class (or copy this also). I've already tried this and it works.


Jul 10, 2008 at 7:15 AM
Thanks AdeMiller
Sorry for posting the replay so late, was busy in some other stuff.

The only option that's working is putting everything in GAC or in the EXCEL.exe directory. Thought I haven't tried changing the AppDomain load behavior.
Jul 10, 2008 at 3:28 PM
This is the behavior I would expect. The assembly loaded will attempt to load DLLs from the GAC and then the app
base folder. Placing your assemblies here has some undersirable side effects we discussed earlier.

I'd encourage you to try the third solution I outlined above. I got this working in under an hour as it involves one minor
change to the classes in the WSSF:ME source and it should just work.

Thanks,

Ade