Correctly locate DLL's App.config section handler assemblies - c#

I am writing a DLL which is loaded by a third party application (The FitNesse framework's test runner, the DLL is a test fixture).
The DLL has its own App.config file (say MyDll.dll.config), and I can tell FitNesse to load that App.config file.
But here's the problem: The App.config file contains custom config section handler, like this:
<configuration>
<configSections>
<sectionGroup name="myGroup">
<section name="MySection" type="MyNamespace.MyHandler.MySection, MyNamespace.MyHandler"/>
...
</sectionGroup>
</configSections>
...
</configuration>
Whenever the App.config file is read, the I get an exception saying that the MyNamespace.MyHandler assembly cannot be found, although it sits in the same folder as the MyDll.dll.config file being read:
System.TypeInitializationException:
The type initializer for
'MyNamespace.MyHandler.MySection'
threw an exception. --->
System.Configuration.ConfigurationErrorsException:
An error occurred creating the
configuration section handler for
myGroup/MySection: Could not load file
or assembly 'MyNamespace.MyHandler' or
one of its dependencies. The system
cannot find the file specified
I can see that the system looks for this file in the same folder where the executable that is loading my DLL is located. However, I do not want to copy my files into this third party directory or vice versa.
Is there a way to specify where the system should look for the DLLs to interpret the App.config file? A general solution or a FitNesse-specific solution would both work for me.
Thanks a lot in advance for any help!

You could try using the runtime section as explained here:
http://kbalertz.com/897297/consume-assemblies-located-folder-different-application-folder-Visual-Basic.aspx

Here's another solution we found ourselves. While the solution presented by Gregor S. indeed seems to enable us to read the App.config, we run into other problems regarding the working directory later. So what we are doing now, is adding the FitNesse Runner application as a link to our project, so that it is picked up from its original location and copied to our test application's folder before it is executed.
It's not nice, but it works.

Related

Application failed to start because its side-by-side configuration is incorrect

I have a c# application and I added a manifest to it and set it to an embedded resource because I didn't want it appearing alongside my exe.
I then changed my app.config file to be an embedded resource as well but my exe then didnt start up as it gave me the error:
"The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe. tool for more detail"
I have since changed it back to 'Do not copy" and I'm still getting the same error.
I have also deleted my app.config file from my project and re-added it. Not I get 2 config files:
App.config and
MyExeName.config
How can I fix this??
We found that our MyExeName.config had a comment block that was NOT CLOSED - thus making the rest of the .config file from that point onward one big comment!

Issue With codeSubDirectories

This is a lengthy one - please bear..!
I have a web-site that currently uses a monolith "app_code" dll file - and am looking at breaking the dll into pieces for better maintenance.
I'm using the section in web.config to split-up my app_code into multiple, folder-wise dll files. The section looks like this:
<codeSubDirectories>
<add directoryName="CodeSubDir1"/>
<add directoryName="CodeSubDir2"/>
...
</codeSubDirectories>
I've created separate sub-folders for each of the .cs files within the "app_code" folder except for a handful of .cs files that refer each other - so needed to be placed together in the same sub-folder. The .cs files are moved to their corresponding sub-folder.
After these changes, there is no .cs file that is directly under the "app_code" folder. I've set the order of the elements within codeSubDirectories such that all other references are taken care of.
The site builds and publishes successfully in my dev. environment. The "Allow this precompiled site to be updatable" and "Used fixed naming and single page assemblies" check-boxes are checked while publishing. No app_code.dll and app_code.compiled files are created during the publish as there are no .cs files directly under the "app_code" folder. Every sub-folder under app_code is published as app_subcode_sub_folder_name.dll and app_subcode_sub_folder_name.compiled.
Both the site and its published version work fine as well in my dev. environment.
After I update the published files to my staging setup [.NET 3.5/IIS 6/Win 2003], I'm getting these two errors [on two separate URLs]:
Error on URL-1:
Could not load file or assembly 'App_Code, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.IO.FileNotFoundException: Could not load file or assembly 'App_Code, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Source File: xxx\v2.0.50727\Temporary ASP.NET Files\xxx\xxx\xxx\App_Web_xxx.8.cs Line: 0
Error on URL-2:
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.
My staging-update process is: I copy the "app_subcode_xxx.dll" and "app_subcode_xxx.compiled" files to the "bin" folder and delete the existing "app_code.dll" and "app_code.compiled" files. I add the codeSubDirectories section to the web.config on staging.
I've searched the GAC, Code and Registry for any reference to the assembly "app_code" with no luck. What am I missing out? Are there any additional steps needed to make this work on my staging site? Do I need to copy ALL other published DLLs as well from dev. to staging?
Copy all the dlls and compiled files from the publish folder to the staging environment. Chances are other dlls and compiled files are still referencing the appcode.

log4net issue when F# script calls C# exe

I got an C# exe which writes log4net logs. If I run this exe directly, the logging works ok.
However, if I call the exe from a F# script (with extension fsx), I have the error
log4net:ERROR Failed to find configuration section 'log4net' in the application'
s .config file. Check your .config file for the <log4net> and <configSections> e
lements. The configuration section should look like: <section name="log4net" typ
e="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
anyone can help? thanks a lot
You should insert configuration of this exe file to configuration file of your f# application or initialize logger in code. I am not sure that when you run f# script there are config file.
You can try to set config to configfile of your c# exe with code:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "c:/test.config);
When you call your C# .exe from F# Interactive, the current working directory -- which is where .NET will try to load the .config file from -- is the directory where F# Interactive is installed.
In your F# interactive script, do something like this:
// Change the current directory to the directory where the
// C# assembly was loaded from.
System.Environment.CurrentDirectory <-
// TODO : Change 'MyType' to any public type from your C# assembly
typeof<FSharpx.Text.Lexing.Position>.Assembly.Location
EDIT : On second thought, I don't know if the above code will work -- it assumes the .config file will be lazily loaded (i.e., on-demand). If the CLR loads the .config file at the same time the .exe is loaded, you'll need to do something like this instead:
// Change the current directory *before* referencing the C# assembly.
System.Environment.CurrentDirectory <- #"C:\blah";;
// Reference the C# assembly
#r #"C:\blah\foobar.exe";;

Apply an App.config to my DLL assembly?

I'm writing a class library as an abstraction to use for logging in any application, service, etc. that I write. I'm making it decently robust by making it very configurable to suit my needs for most application/service logging scenarios that I come across.
The config is designed to specify things such as:
What logging level to write
Write to one log file for all levels
Write to separate files per level
Logging cutoff (periodic, app event, byte size restricted)
Log file expiration (delete log files after file age)
Write as flat text or XML
Log file name format specification
Whether to prefix filename with date
Parent app's name
etc, etc, etc...
I've read some other stackoverflow questions regarding configs for DLL assemblies and it causing conflict between the app.config for the hosting assembly/app. I believe that my assembly has just cause to provide a config file.
Is this a good scenario for that occasion? Is it perhaps a better idea to bake my own config into my project so that my logger reads from XML files to retrieve config values?
What you could do is
create a custom configuration section (using e.g. the COnfiguration Section Designer tool)
put your assembly's configuration into a separate MyAssembly.config file
reference that assembly config file from your host app's config:
<configuration>
<configSections>
<section name="YourAssembly"
type="YourAssembly.ConfigSection, YourAssembly" />
</configSections>
<YourAssembly configSource="MyAssembly.config" />
</configuration>
That way, you can "externalize" your configuration into a separate config file which you have only once (in your assembly's project), and any project needing it just needs those settings in its own config file.
Sounds like a custom config section would work well in your case. Many libraries, such as the Enterprise Library do exactly this. Check out the MSDN article about creating one.
The .NET config mechanism is not meant to handle configuration files for DLLs. You should configure your application with appropriate settings and pass them on to the class you are instantiating from the DLL.
It is possible to add settings to a DLL project as you'd usually do for applications. All you then need to do is copy the relevant sections and entries into the application's app.config manually and it will work.
It is, however, still true that there's no point copying the DLL's config file. It will not be read.
Another mechanism is to have a seperate configuration file (*.dll.config) for your assembly. The technique is shown here: http://blog.rodhowarth.com/2009/07/how-to-use-appconfig-file-in-dll-plugin.html
The above, imitate the standard app.config technique for assemblies.
In my opinion the dll configuration reading code should only exist in the corresponding dll and in a seperate class - with single responsibility of reading configuration entries from the *.dll.config. This is a nice way of having configuration file for an assembly in a way similar to the configuration file (app.config) an executable can have.

Windows Service Config File C#

I've developed a windows service application using Visual Studio 2008 / C#.
I have an app.config file in the project. When installed, the app.exe.config file appears beside the executable but it appears not to be reading the values from it when I try to access them through ConfigurationManager.AppSettings.
Has it copied the config file elsewhere or is there some other problem I don't know about?
Thanks in advance,
Martin.
Edit:
The config file name is infact my_exe_file_name.exe.config, it looks like:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="RuntimeFrequency" value="3" />
</appSettings>
</configuration>
and I am trying to read via:
ConfigurationManager.AppSettings["RuntimeFrequency"]
The debug value I continually see is '1' and not '3'. Am I doing something wrong here?
I located the error and it was related to file permissions. After installing the service, my local user account didn't have access to modify the app.exe.config file.
The tool I was using to edit was not informing me it was being denied access to save the file - that's notepad++ if anyone is interested - so I couldn't see that it wasn't saving over the old config file.
Solved now, thanks everyone.
Martin.
When you are in debug mode check and see what settings are in the my_exe_file_name.vshost.exe.config Also make sure you adjust this in the app.config file. Visual studio should update the final config file in your bin/debug folders.
Maybe you are updating the wrong config file. You should double check that using
System.Configuration.ConfigurationManager.OpenExeConfiguration(PATH_TO_CONFIG);
Generally for the Windows Services that I write, i drop the appName.exe.config file into C:\WINDOWS\system32\
Perhaps you have an older version in that directory, which is where your service is getting the value, even though you've updated the config file in your project.
App.config file should be renamed to your_exe_file_name.exe.config and placed near the exe file.
Is it possible that you have more than one instance of the RuntimeFrequency entry defined? The ConfigurationManager reads the file from top to bottom and processes each setting individually. Therefore, the last value of RuntimeFrequency that is defined in the file is the one it will use.
If you want to know for sure if your file is being used, I would simply remove or comment out any definition for RuntimeFrequency (copy/paste errors do happen) and wait to see an application error when ConfigurationManager attempts to reference an entry in AppSettings that does not exist.

Categories

Resources