I have a c# .Net console app that performs FTP operations. Currently, I specify the settings in a custom configuration section, e.g.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="ftpConfiguration" type="FileTransferHelper.FtpLibrary.FtpConfigurationSection, FileTransferHelper.FtpLibrary" />
</configSections>
<ftpConfiguration>
<Environment name="QA">
<sourceServer hostname="QA_hostname"
username="QA_username"
password="QA_password"
port="21"
remoteDirectory ="QA_remoteDirectory" />
<targetServer downloadDirectory ="QA_downloadDirectory" />
</Environment>
</ftpConfiguration>
</configuration>
I would like to specify, in the command line, an external configuration file.
HOWEVER!!!...
I just realized that the above "FtpConfiguration" section doesn't truly belong in the application's app.config. My ultimate goal is that I will have many scheduled tasks that execute my console app like this:
FileTransferHelper.exe -c FtpApplication1.config
FileTransferHelper.exe -c FtpApplication2.config
...
FileTransferHelper.exe -c FtpApplication99.config
Consequently, I believe I've gone down the wrong path and what I really want is something to read in my custom xml document but continue to use System.Configuration to get the values... as opposed to reading an XmlDocument and serializing it to get nodes/elements/attributes. (Although, I'm not against the latter if someone can show me some simple code)
Pointers would be greatly appreciated. Thanks.
Update: The answer I accepted was a link to another StackOverflow question, repeated here with my code - below which was exactly what I was looking for -- using the OpenMappedExeConfiguration to open my external config file
ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap();
configFileMap.ExeConfigFilename = @"D:\Development\FileTransferHelper\Configuration\SampleInterface.config";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
FtpConfigurationSection ftpConfig = (FtpConfigurationSection)config.GetSection("ftpConfiguration");
To open a CFG file using the native Notepad app, open Windows File Explorer at the location of the file. If Windows automatically recognizes the CFG file, double-click it to open it in Notepad. Alternatively, right-click the CFG file and select the Open With option.
conf file in Linux, first locate it in the file system. Most often, the dhclient. conf file will be located in the /etc or /etc/DHCP directory. Once you find the file, open it with your favorite command-line editor.
If you want to use System.Configuration to open your custom files, you may want to check on this post: Loading custom configuration files. Oliver nails it in a very straightforward way.
Since you want to read parameters passed to your application via the command line, you may want to pay a visit to this MSDN post: Command Line Parameters Tutorial.
If you'd rather use a custom approach, there's a few ways you can accomplish this. One possibility is to implement a loader class, and consume your custom configuration files.
For example, let's assume a simple config file that looks like this:
spec1.config
<?xml version="1.0" encoding="utf-8"?> <Settings> <add key="hostname" value="QA_hostname" /> <add key="username" value="QA_username" /> </Settings>
A very simple, hashtable-like (key-value pair) structure.
An implemented parser/reader would then look something like this:
private Hashtable getSettings(string path) { Hashtable _ret = new Hashtable(); if (File.Exists(path)) { StreamReader reader = new StreamReader ( new FileStream( path, FileMode.Open, FileAccess.Read, FileShare.Read) ); XmlDocument doc = new XmlDocument(); string xmlIn = reader.ReadToEnd(); reader.Close(); doc.LoadXml(xmlIn); foreach (XmlNode child in doc.ChildNodes) if (child.Name.Equals("Settings")) foreach (XmlNode node in child.ChildNodes) if (node.Name.Equals("add")) _ret.Add ( node.Attributes["key"].Value, node.Attributes["value"].Value ); } return (_ret); }
Meanwhile, you'll still be able to use ConfigurationManager.AppSettings[]
to read from the original app.config
file.
If you going down the custom path, I honestly would just use JSON to store the config and then deserialize to load it and serialize to write it. Json.NET allows you to do this very easily.
Your XML of:
<ftpConfiguration> <Environment name="QA"> <sourceServer hostname="QA_hostname" username="QA_username" password="QA_password" port="21" remoteDirectory ="QA_remoteDirectory" /> <targetServer downloadDirectory ="QA_downloadDirectory" /> </Environment> </ftpConfiguration>
Would look like this in JSON:
{ "FtpConfiguration": { "Environment": { "Name": "QA", "SourceServer": { "HostName": "QA_hostname", "UserName": "QA_username", "Password": "QA_password", "Port": "21", "RemoteDirectory": "QA_remoteDirectory" }, "TargetServer": { "DownloadDirectory": "QA_downloadDirectory" } } } }
Your classes would look like:
class Config { public FtpConfiguration FtpConfiguration { get; set; } } class FtpConfiguration { public Environment Environment { get; set; } } class Environment { public SourceServer SourceServer { get; set; } public TargetServer TargetServer { get; set; } } class SourceServer { public string HostName { get; set; } public string UserName { get; set; } public string Password { get; set; } public int Port { get; set; } public string RemoteDirectory { get; set; } } class TargetServer { public string DownloadDirectory { get; set; } }
You would save setting into an object like this:
var config = new Config() { FtpConfiguration = new FtpConfiguration() { Environment = new Environment() { SourceServer = new SourceServer() { HostName = "localhost", UserName = "jaxrtech", Password = "stackoverflowiscool", Port = 9090, RemoteDirectory = "/data", }, TargetServer = new TargetServer() { DownloadDirectory = "/downloads" } } } };
You then could write to the file like this (or use a Stream
if its a bigger file):
string json = JsonConvert.SerializeObject(config); File.WriteAllText("config.json", json);
You then could read in the file like this (again you could use a Stream
instead):
string json = File.ReadAllText("config.json"); Config config = JsonConvert.DeserializeObject<Config>(json);
My preferred solution uses an XDocument. I haven't tested it, so there may be some slight issues, but this is to demonstrate my point.
public Dictionary<string, string> GetSettings(string path)
{
var document = XDocument.Load(path);
var root = document.Root;
var results =
root
.Elements()
.ToDictionary(element => element.Name.ToString(), element => element.Value);
return results;
}
Will return a dictionary containing the element names and values from xml of the form:
<?xml version="1.0" encoding="utf-8"?>
<root>
<hostname>QA_hostname</hostname>
<username>QA_username</username>
</root>
I find this solution nice because of it's overall brevity.
Again, I don't expect this to work exactly as is. Using XAttributes and XElements and such, you can definitely make this more like your original. It will be easy to filter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With