Multiple `.settings` Files Based on Configuration - c#

I wanted to know if there was a way to have multiple .settings files based on configuration that are honored at runtime. So, at the moment I have a Settings.settings and a Release.settings file under the Properties folder. I'm not saying this is right by any means, I'm just saying that's what I currently have.
But, when running this line of code I always get the value out of the Settings.settings file.
Properties.Settings.Default.Setting
I realize that the Settings part of that line is explicitly defining the file I want, but I'm trying to find a way to get an abstracted line of code that will pull it out based off of the configuration.
So, unlike a config transform where it can be used to simply produce a different version of the file on deployment, I need to be able to actually see different values at runtime based on the configuration I'm running under.
I hope somebody can help, and thanks!

Yes it is possible. I was just wanting to do the same thing myself.
From the Project menu, choose Add New Item. The Add New Item dialog
box opens.
In the Add New Item dialog box, select Settings File, type in a name
for the file, and click Add to add a new settings file to your
solution.
In Solution Explorer, drag the new Settings file into the Properties
folder. This allows your new settings to be available in code.
Add and use settings in this file as you would any other settings
file. You can access this group of settings via the
Properties.Settings object.
Then you can reference each settings file by its prefix.
Config config = new Config();
if (Debugger.IsAttached)
{
config = new Config()
{
Interval = Dev.Default.Interval,
Username = Dev.Default.Username,
Password = Dev.Default.Password,
Directory = Dev.Default.Directory
};
}
else
{
config = new Config()
{
Interval = Settings.Default.Interval,
Username = Settings.Default.Username,
Password = Settings.Default.Password,
Directory = Settings.Default.Directory
};
}

Related

C#: opening a text file stored within the same project as the app

I managed to open a text file using an absolute path (in Visual Studio 2017) although if I change the location of my Solution folder the whole code would not work anymore as the actual physical path has changed and the code can not reference an existing location anymore.
I tried to create a text file within the same project and I would now like to open this file in my code, so if the location of the whole Solution changes the program can still work, would anyone be so kind to help me fix this issue?
I have also looked online for some different solution using code that references the current directory but I can't get my head around it as the current directory seems to be bin/debug and if I try to insert the file there the code doesn't recognize the location (also it doesn't look like a clean solution to me).
This is the code I am using so far in a WPF app, the whole purpose is to open the content of the text file containing countries listed line by line and to add them to a list box which will be displayed when a checkbox will be ticked.
private void listCountry_Initialized(object sender, EventArgs e)
{
listCountry.Visibility = Visibility.Hidden;
string path = "C:\\Users\\david\\source\\repos\\StudentRecord\\StudentRecordSystemMod\\StudentRecord\\country.txt";
if (File.Exists(path))
{
string[] myCountryFile = File.ReadAllLines(path);
foreach (var v in myCountryFile)
{
listCountry.Items.Add(v);
}
}
}
This is a great use case for OpenFileDialog Class.
Represents a common dialog box that allows a user to specify a filename for one or more files to open.
Here is the example of use, from the documentation.
// Configure open file dialog box
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.FileName = "Document"; // Default file name
dlg.DefaultExt = ".txt"; // Default file extension
dlg.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
// Open document
string filename = dlg.FileName;
}
Assuming C:\\Users\\david\\source\\repos\\StudentRecord\\StudentRecordSystemMod\\ is your project, and StudentRecord\\country.txt is a project folder and file in your project - you need change "Copy to Output Directory" to be "Always Copy" or "Copy If Newer" and "Build Action" to "Content" for the file in your project.
As you can see from the screenshot above, the folder structure for this content is created as well.
Then change your path assignment to be something like the following:
string path = string.Join(#"\", Application.ExecutablePath, #"StudentRecord\country.txt");
Clean and simple, place the file you want to open next to where the executable is generated, remember the executable path changes depending to if your project is in Debug or Release build mode. Now set:
string path = "country.txt";
By only providing a filename, the file is looked for in the same folder as the executable. Just remember that when you move the executable you must also move the file to the same place, but if you move the entire project folder then you're already set.
However, if you want to keep your file in a fixed location regardless of where you have your executable and/or VS project files, then the simplest path for it is:
string path = "C:\\country.txt";
This is an absolute path, but it's quite simple and very robust to changes, you would have to change the drive letter to break it and if C: is where your operating system files are then you probably won't do that.
If you don't like to have your files around in your root, you can always have a path like this:
string path = "C:\\ProjectNameFiles\\country.txt";
Or if you prefer to maintain a hierarchy of projects then you can use:
string path = "C:\\MyProjectsFiles\\ProjectName\\country.txt";
With this, every project can have a directory for the files it needs to open. These are all absolute paths, but are notably simpler than the one you posted, and they have a more fixed and organized structure.

How to add and retrieve string values from configuration file in c#

I have a list box and that list box contain multiple string value. I want to add those strings to config file and want to read values from config and put it in list box. what should be the approach? I am new to configuration file.
The following snippet will help you modify the app.config file of your project.
Configuration config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
config.AppSettings.Settings.Remove("MySetting");
config.AppSettings.Settings.Add("MySetting", "some value");
config.Save(ConfigurationSaveMode.Modified);
For reading the config values, you can simply use ConfigurationManager.AppSettings["MySetting"]
You can store and retrieve configuration data for your app via it's app.config file.
You'll need to add a reference to System.Configuration in your code and add the System.Configuration assembly to your application.
Here is a good post with more info - What is App.config in C#.NET? How to use it?
probably you wanted to have those values present in a file and then read from that file and attach to your listbox like
string path = #"c:\temp\MyTest.txt";
if (File.Exists(path))
{
string[] readText = File.ReadAllLines(path);
}
You can attach that your listbox
listbox1.DataSource = new List<string>().AddRange(readText);

Location of file is unchanged after changing List of folders via Roslyn

I'm trying to change file location of existing file via Roslyn.
var msWorkspace = MSBuildWorkspace.Create();
var solution = msWorkspace.OpenSolutionAsync(Constants.pathToSolution).Result;
DocumentId documentIdToMove = ConsoleHelpers.GetDocumentIdForDocumentWithName(solution, "Person.cs");
var newSolution = solution.WithDocumentFolders(documentIdToMove, new List<string> { "SecondLevel", "ThirdLevel" });
msWorkspace.TryApplyChanges(newSolution);
Originally, the file is in the "SecondLevel" folder inside main project folder.
According to documentation, WithDocumentFolders method should create a new solution instance with the document specified updated to be contained in
the sequence of logical folders.
After running the code, program is completed without any exceptions, file is changed on disk, but the location remains the same. Also, TryApplyChanges method returns true.
When creating new document in a project and then saving changes to disk, the new file is created in location specified by the sequence of folders without any issues.
Is changing location of existing file in project and then saving the changes to disk possible?
Changing folders like this isn't supported. Feel free to file a bug on GitHub.

Using a Windows application to modify settings used by a Windows service

I currently have a Windows service (running as LocalSystem) which I'm installing using InstallSheild LE. This service is meant to read some data from a local database file, package it up, and post it to an external server on a set interval. Rather that have the database location, server url, etc. hard coded I want to read them from a settings file. I can do that easily enough with App.config, but from my research I'm getting the picture that modifying the App.config (or any file in Program Files) is difficult/impossible post installation.
My question is what would be the best way to have an application which I can run to modify the necessary settings for the service without having to "Run as Administrator". Should I be putting these settings in the Registry. Is putting them in AppData the right answer and if so how are those settings shared between the settings changing application and the service?
I'm more of a web application developer and don't yet have much experience with desktop application/service development so any point in the right direction would be much appreciated.
You can locate the App.Config outside of the application install directory and place it in a common folder (like AppData). You'll then tell your application to load it from there instead of just pulling it in from the application install directory.
ConfigurationManager.OpenMappedExeConfig allows you to load your config from a custom location.
// Access a configuration file using mapping.
// This function uses the OpenMappedExeConfiguration
// method to access a new configuration file.
// It also gets the custom ConsoleSection and
// sets its ConsoleEment BackgroundColor and
// ForegroundColor properties to green and red
// respectively. Then it uses these properties to
// set the console colors.
public static void MapExeConfiguration()
{
// Get the application configuration file.
System.Configuration.Configuration config =
ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.None);
Console.WriteLine(config.FilePath);
if (config == null)
{
Console.WriteLine(
"The configuration file does not exist.");
Console.WriteLine(
"Use OpenExeConfiguration to create the file.");
}
// Create a new configuration file by saving
// the application configuration to a new file.
string appName =
Environment.GetCommandLineArgs()[0];
string configFile = string.Concat(appName,
".2.config");
config.SaveAs(configFile, ConfigurationSaveMode.Full);
// Map the new configuration file.
ExeConfigurationFileMap configFileMap =
new ExeConfigurationFileMap();
configFileMap.ExeConfigFilename = configFile;
// Get the mapped configuration file
config =
ConfigurationManager.OpenMappedExeConfiguration(
configFileMap, ConfigurationUserLevel.None);
// Make changes to the new configuration file.
// This is to show that this file is the
// one that is used.
string sectionName = "consoleSection";
ConsoleSection customSection =
(ConsoleSection)config.GetSection(sectionName);
if (customSection == null)
{
customSection = new ConsoleSection();
config.Sections.Add(sectionName, customSection);
}
else
// Change the section configuration values.
customSection =
(ConsoleSection)config.GetSection(sectionName);
customSection.ConsoleElement.BackgroundColor =
ConsoleColor.Green;
customSection.ConsoleElement.ForegroundColor =
ConsoleColor.Red;
// Save the configuration file.
config.Save(ConfigurationSaveMode.Modified);
// Force a reload of the changed section. This
// makes the new values available for reading.
ConfigurationManager.RefreshSection(sectionName);
// Set console properties using the
// configuration values contained in the
// new configuration file.
Console.BackgroundColor =
customSection.ConsoleElement.BackgroundColor;
Console.ForegroundColor =
customSection.ConsoleElement.ForegroundColor;
Console.Clear();
Console.WriteLine();
Console.WriteLine("Using OpenMappedExeConfiguration.");
Console.WriteLine("Configuration file is: {0}",
config.FilePath);
}
Sample Source: MSDN

How to read user settings in app.config from a diff app?

I have a WinForms .exe with an App.config that has a bunch of User Scoped Settings that are set at runtime and saved.
I want to be able to use the WinForms app to change and save the settings and then click on button to do some work based on the those settings.
I also want to read the user settings in the same .config file from a sep. console app so I can schedule to work to be done as a scheduled task.
What is the best way to be able to do this?
Update:
I tried the reccommendation of using ConfigurationManager.OpenExeConfiguration as described in some of the answers like so.
Configuration config = ConfigurationManager.OpenExeConfiguration("F:\\Dir\\App.exe");
but when I try to retrieve a User Setting like so.
string result = config.AppSettings.Settings["DB"].ToString();
I get a Null reference error.
From code in the exe however the following correctly returns the DB name.
Properties.Settings.Default.DB
Where am I going wrong?
Update 2:
So based on some of the answers below I now can use the following to retrieve the raw XML of the section of the user.config file I am interested in from sep. ConsoleApp.
System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = #"D:\PathHere\user.config";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap,ConfigurationUserLevel.None);
System.Configuration.DefaultSection configSection = (System.Configuration.DefaultSection)config.GetSection("userSettings");
string result = configSection.SectionInformation.GetRawXml();
Console.WriteLine(result);
But I am still unable to just pull the value for the specific element I am interested in.
this should do it :
var clientSettingsSection = (System.Configuration.ClientSettingsSection)(ConfigurationManager.GetSection("userSettings/YourApplicationName.Properties.Settings"));
var setting = clientSettingsSection.Settings.Get("yourParamName_DB_");
string yourParamName_DB = ((setting.Value.ValueXml).LastChild).InnerText.ToString();
You can use the ConfigurationManager class to open the configuration file of another executable.
Configuration conf = ConfigurationManager.OpenExeConfiguration(exeFilePath);
// edit configuration settings
conf.Save();
See ConfigurationManager.OpenExeConfiguration
If you are setting these values per user basis you may need to use the ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel) method instead of the current method you are using now.
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Environment.CurrentDirectory + "\\MyApp.exe.config";
//i have config in the same directory as my another app
System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
var settingsSection = (System.Configuration.ClientSettingsSection)config.GetSection("userSettings/MyApp.Properties.Settings");
var setting = settingsSection.Settings.Get("MySetting");
var param = ((setting.Value.ValueXml).LastChild).InnerText.ToString();
If you know the path to the config file try:
System.Configuration.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration("configPath");
string myValue = config.AppSettings.Settings[ "myValue" ].Value;

Categories

Resources