I want to use a .NET settings file in an external dll library. This article explains exactly what I am trying to do.
partial class LastState
{
public LastState() : base(new ConfigurationFileApplicationSettings("LastState.config", typeof(LastState))) { }
}
Unfortunately, using this implementation, it is not possible to save settings back to the config file. If I try to use Save(), SetPropertyValues throws a NotSupportedException. Is there any way to save a .NET settings file from an external dll library?
I would use custom configuration files.
ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
configMap.ExeConfigFilename = #"d:\test\justAConfigFile.config.whateverYouLikeExtension";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel)
Have a look here for more détails.
You can save with
config.AppSettings.Settings["YourThing"].Value = "New Value";
config.Save();
Related
I have 12 projects in my solution file. There are most Windows services (ServiceProj_1, ServiceProj_2, ...) and one project is of web application (WebApp). I use log4net for logging. WebApp and ServiceProject_1, ServiceProj_2, ... have log4net configuration into web.config and app.config files respectively. We have implemented a DMZ, so the WebApp is only exposed to the other people. Now there is a requirement to use logging of those windows service projects instead of WebApp.
I have come to know that I can create a custom appender and make it possible. The catch is, there are lots of lines already written into WebApp to log a LogMessage into log file so we cannot touch those lines.
I have no idea what to do and how to do. Need help.
If the description is not understandable then please let me know I will try to explain more.
You can specify the config file and load it dynamically...
Here my config file is found at the location of FullConfigFilePath.
private Configuration Config
{
get
{
if (_Config != null) return _Config;
_Config = ConfigurationManager.OpenMappedExeConfiguration(
new ExeConfigurationFileMap()
{
ExeConfigFilename = FullConfigFilePath
}, ConfigurationUserLevel.None);
return _Config;
}
}
Once the config is loaded you can access the values from there....
For instance.....
private string BaseUrl
{
get
{
return this.Config.AppSettings.Settings["MyConfigSetting"].Value;
}
}
Hopefully you can tweak and use this sort of approach for your needs.
I initialized the interactive element with the project from the context menu of my project.
I am testing a function in C# interactive that needs to read my app.config file to get a connectionstring.
I got the next error:
No connection string named 'ccnName' could be found in the application config file.
When I use the next code, i get a null value. I suppose it is because it is not reading the app.config of my project.
ConfigurationManager.ConnectionStrings["cnnName"]
It is the only connectionstring that the default app.config has:
[data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true]
In this post from 2012 with the same topic, one engineer involved in this project said that this option was not available. I hope it is available now in 2018
So, nowadays how can i load the app.config that i want?
"Constructor" was the magic word. This may not help in your case since you've found a solution, but it might be helpful for others in the same situation.
If you inject a System.Configuration.Configuration object into the class, you don't have to rely on ConfigurationManager's static properties.
public class LibraryClass
{
private Configuration _configuration;
public LibraryClass(Configuration configuration)
{
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
}
public void FunctionUnderTest()
{
string connectionString = _configuration.ConnectionStrings.ConnectionStrings["cnnName"].ConnectionString;
// Connect to the database as you normally would.
}
}
In a console/GUI application and unit tests, load it like this to use {anything}.config:
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Register 'configuration' as a singleton using the container of your choice.
In a web application, load it like this to use web.config:
Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~/Web.config");
// Register 'configuration' as a singleton using the container of your choice.
To use it in C# Interactive, load it using the first method and provide the dependency to the class directly:
#r "System.Configuration"
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(
new ExeconfigurationFileMap() { ExeConfigFilename = #"path\to\Arbitrary.config" },
ConfigurationUserLevel.None);
var lib = new LibraryClass(configuration);
lib.FunctionUnderTest();
Note that the section properties are an extra layer deep compared to what you would normally expect.
I think it has something to do with how ConfigurationManager's static properties work with the Configuration instance.
I'm trying to unit test a custom ConfigurationSection I've written, and I'd like to load some arbitrary configuration XML into a System.Configuration.Configuration for each test (rather than put the test configuration xml in the Tests.dll.config file. That is, I'd like to do something like this:
Configuration testConfig = new Configuration("<?xml version=\"1.0\"?><configuration>...</configuration>");
MyCustomConfigSection section = testConfig.GetSection("mycustomconfigsection");
Assert.That(section != null);
However, it looks like ConfigurationManager will only give you Configuration instances that are associated with an EXE file or a machine config. Is there a way to load arbitrary XML into a Configuration instance?
There is actually a way I've discovered....
You need to define a new class inheriting from your original configuration section as follows:
public class MyXmlCustomConfigSection : MyCustomConfigSection
{
public MyXmlCustomConfigSection (string configXml)
{
XmlTextReader reader = new XmlTextReader(new StringReader(configXml));
DeserializeSection(reader);
}
}
You can then instantiate your ConfigurationSection object as follows:
string configXml = "<?xml version=\"1.0\"?><configuration>...</configuration>";
MyCustomConfigSection config = new MyXmlCustomConfigSection(configXml);
Hope it helps someone :-)
I think what you're looking for is ConfigurationManager.OpenMappedExeConfiguration
It allows you to open a configuration file that you specify with a file path (wrapped inside a ExeConfigurationFileMap)
If what the other poster said is true, and you don't wish to create a whole new XML file for testing, then I'd recommend you put your Configuration edits in the Test method itself, then run your tests against the freshly changed configuration data.
Looking at the members of the class, I'd say the answer is probably no*. I'm not sure why you'd want to do this anyway, rather than create your own XML configuration file.
*That's no, excluding messy reflection hacks
I'm working on a setup project. In a separate library project I created a custom installer by inheriting from System.Configuration.Install.Installer and added the generated .dll as a custom action.(Install step). I added an app.config file to the library project where I store a connection string which I need to make a connection to Sql Server.
Once I run the setup project, the custom installer doesn’t retrieve the connectionString stored in the app.config file.
Where can I store the connection string? Can a setup project have an app.config? Could somebody recommend a book on deployment/setup projects?
Thanks
UPDATE
Hi,
Thanks. Based on the replies I've updated my code this is what I´m doing now:
-> In setup project, I added a custom action to the install step, selecting application folder and primary output(library project).
-> Added an app.config to the library project and set its build action to "content".
-> Added the library project content files to the setup project.
This way the app.config file appears in the install folder.
Within the install handler from my custom install class I do the following: (in this case I access the application settings)
string appPath = "";
appPath = Path.Combine(new DirectoryInfo(Context.Parameters["assemblypath"].ToString()).Parent.FullName, "App.config");
ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = appPath;
System.Configuration.Configuration c = null;
c = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
string result = c.AppSettings.Settings["test"].Value;
You can still reuse app.config if you insist on doing so, but you need to come up with your own way to parse it.
Here is the necesary steps for this workaround:
Create your own mechanism to
read the appSettings using
System.Xml.XmlReader or whatever from
the app.config file that will be
copied into the Application Folder.
Use your custom xml parser to
extract the value and use it in your
custom action.
Mark
App.config as Content in the Build Action property
window (in the custom action project).
In the Setup Project, add Project Output in the Application Folder and choose Content Files
instead of Primary output. You can
verify that app.config is the output
by invoking context menu and choosing
Outputs for the Content Files from
... item.
After you've done this, you should have 2 outputs from the Custom Installer class library project (1 for Primary output and 1 for the Content Files).
Here is an example custom installer action that will launch whatever I have in my appSettings key called launch along with my replacement ConfigurationManager implementation:
using System;
using System.Configuration.Install;
using System.Xml;
using System.IO;
using System.Reflection;
using System.ComponentModel;
using System.Collections;
namespace ClassLibrary1
{
[RunInstaller(true)]
public partial class Installer1 : System.Configuration.Install.Installer
{
public Installer1()
{
InitializeComponent();
}
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
public override void Commit(IDictionary savedState)
{
base.Commit(savedState);
System.Diagnostics.Process.Start(ConfigurationManager.AppSettings["launch"]);
}
}
public class ConfigurationManager
{
private static AppSetting _appSettings = new AppSetting();
public static AppSetting AppSettings
{
get { return _appSettings; }
}
public class AppSetting
{
public string this[string key]
{
get
{
var path = Path.Combine(Path.GetDirectoryName(Assembly.GetCallingAssembly().Location), "app.config");
var xpath = string.Format("/configuration/appSettings/add[#key='{0}']", key);
var doc = new XmlDocument();
doc.Load(path);
var node = doc.SelectSingleNode(xpath);
if (node == null)
return string.Empty;
return node.Attributes["value"].Value;
}
}
}
}
}
Instead of trying to parse the app.config, I would suggest adding the configSource attribute to your app.config to externalize the connection strings, something like:
<connectionStrings configSource="connections.config" />
Then get the setup script to generate the entire connections.config file, similar to:
<connectionStrings>
<clear />
<add name="...." connectionString="...." providerName="...." />
</connectionStrings>
Make sure you use .config as the extension of your file so it cannot be served to the browser if someone guesses the file name.
I'm trying to unit test a custom ConfigurationSection I've written, and I'd like to load some arbitrary configuration XML into a System.Configuration.Configuration for each test (rather than put the test configuration xml in the Tests.dll.config file. That is, I'd like to do something like this:
Configuration testConfig = new Configuration("<?xml version=\"1.0\"?><configuration>...</configuration>");
MyCustomConfigSection section = testConfig.GetSection("mycustomconfigsection");
Assert.That(section != null);
However, it looks like ConfigurationManager will only give you Configuration instances that are associated with an EXE file or a machine config. Is there a way to load arbitrary XML into a Configuration instance?
There is actually a way I've discovered....
You need to define a new class inheriting from your original configuration section as follows:
public class MyXmlCustomConfigSection : MyCustomConfigSection
{
public MyXmlCustomConfigSection (string configXml)
{
XmlTextReader reader = new XmlTextReader(new StringReader(configXml));
DeserializeSection(reader);
}
}
You can then instantiate your ConfigurationSection object as follows:
string configXml = "<?xml version=\"1.0\"?><configuration>...</configuration>";
MyCustomConfigSection config = new MyXmlCustomConfigSection(configXml);
Hope it helps someone :-)
I think what you're looking for is ConfigurationManager.OpenMappedExeConfiguration
It allows you to open a configuration file that you specify with a file path (wrapped inside a ExeConfigurationFileMap)
If what the other poster said is true, and you don't wish to create a whole new XML file for testing, then I'd recommend you put your Configuration edits in the Test method itself, then run your tests against the freshly changed configuration data.
Looking at the members of the class, I'd say the answer is probably no*. I'm not sure why you'd want to do this anyway, rather than create your own XML configuration file.
*That's no, excluding messy reflection hacks