how to use an external configuration file with WPF? - wpf

i would like to set up an external configuration file that I can store in a directory for my WPF app, not necessarily the directory of my exe when I create my program either.
I created an App.Config file and added System.Configuration to my assembly. My App.Config has:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings file="sd.config">
<add key="username" value="joesmith" />
</appSettings>
</configuration>
and my sd.config (external file) which is in the root of my project for now, has
<?xml version="1.0"?>
<appSettings>
<add key="username1" value="janedoe" />
</appSettings>
in my MainWindow cs class I used
string username = ConfigurationManager.AppSettings.Get("username1");
which returns a null string. when i just retrieve the username field from App.Config it works. What did i miss? Thanks so much!

See the documentation on ConfigurationManager:
The AppSettings property:
Gets the AppSettingsSection data for the current application's default
configuration.
You need to do a little extra work to get data that isn't in your application's default configuration file.
Instead of using the file= attribute, add a key to your <appSettings> that defines the location of the secondary config file, like so:
<add key="configFile" value="sd.config"/>
Then, in order to use ConfigurationManager to pull settings from the secondary config file, you need to use its OpenMappedExeConfiguration method, which should look a little something like this:
var map = new ExeConfigurationFileMap();
map.ExeConfigFilename = Path.Combine(
AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
ConfigurationManager.AppSettings["configFile"]
);
//Once you have a Configuration reference to the secondary config file,
//you can access its appSettings collection:
var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
var userName1 = config.AppSettings["username1"];
That code might not be dead-on for your example, but hopefully it gets you on the right track!

Related

How to use .env file data in a .xml file in React

I am using React and would like to use the data within the .env file and insert it into my .xml file.
Is this achievable somehow, could not find anything useful on the net?
The file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="TaskPaneApp">
<!--IMPORTANT! Id must be unique for each add-in. If you copy this manifest ensure that you change this id to your own GUID. -->
<Id>c6890c26-5bbb-40ed-a321-37f07909a2f0</Id>
<Version>1.0</Version>
<ProviderName>Contoso, Ltd</ProviderName>
<DefaultLocale>en-US</DefaultLocale>
<DisplayName DefaultValue="Northwind Traders Excel" />
<Description DefaultValue="Search Northwind Traders data from Excel"/>
<SupportUrl DefaultValue="[Insert the URL of a page that provides support information for the app]" />
<AppDomains>
<AppDomain>https://www.northwindtraders.com</AppDomain>
</AppDomains>
<DefaultSettings>
<SourceLocation DefaultValue="https://www.contoso.com/search_app/Default.aspx" />
</DefaultSettings>
<Permissions>ReadWriteDocument</Permissions>
</OfficeApp>
And instead of the lets say Id property i would like to have some preset value from .env.

Where are the settings saved in a .NET 5 WinForms app?

In a .NET Framework WinForms project, there was an App.config file in the project, which was an XML file that contained a configSection that would reference a class in System.Configuration, and a section for the userSettings themselves, like so:
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561944e089">
<section name="MyAppName.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561944e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<MyAppName.Properties.Settings>
<setting name="Test" serializeAs="String">
<value>Some Value</value>
</setting>
</MyAppName.Properties.Settings>
</userSettings>
And this created a file in the build folder with the app name plus .exe.config, as in MyAppName.exe.config.
But when I create a new WinForms project using .NET:
There is no App.config in the solution. I can edit the settings using the project properties:
And I can access these values, and update them using the same Properties object and methods:
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
textBox1.Text = Properties.Settings.Default.Test;
}
private void button1_Click(object sender, EventArgs e)
{
Properties.Settings.Default.Test = textBox1.Text;
Properties.Settings.Default.Save();
}
}
}
And everything seems to work, but when I examine the bin folder, there is no file that I can see for where the values are actually stored.
Where is .NET 5 storing the saved application settings if not in a file in the same folder as the application's exe?
User settings are stored in user.config file in the following path:
%userprofile%\appdata\local\<Application name>\<Application uri hash>\<Application version>
Application settings file are not created by default (unexpectedly), however if you create them manually beside the dll/exe file of your application, the configuration system respect to it. The file name should be <Application name>.dll.config. Pay attention to the file extension which is .dll.config.
You may want to take a look at the source code of the following classes:
LocalFileSettingsProvider (The default setting provider)
ClientSettingsStore
ConfigurationManagerInternal
ClientConfigurationPaths
At the time of writing this answer Application Settings for Windows Forms still doesn't have any entry for .NET 5 and redirects to 4.x documentations.
First of all, this is a known (to .NET team) issue: https://github.com/dotnet/project-system/issues/7772.
Secondly the issue and the solution are pretty much described in your question:
(before) ..there was an App.config file in the project,..
(now) There is no App.config in the solution...
Add the missing app.config and everything will work just like it did before.

How to resolve key/value pair with external .config file

I am specifying <appSettings> in my app.config file, I am adding
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings configSource="ShareAppSettings.debug.config"/>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
</startup>
</configuration>
ShareAppSettigns.debug.config is my external config file, which I am using on my local machine and I do not want to share it with the rest of my team.
ShareAppSettings.debug.config looks like:
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<add key="clientID" value="11" />
<add key="clientSecret" value="11" />
<add key="tenantID" value="11" />
</appSettings>
Whenever I am trying to debug the main code:
private static List<string> AppCredentials()
{
string clientID = ConfigurationManager.AppSettings["clientID"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
string tenantID = ConfigurationManager.AppSettings["tenantID"];
List<string> appCred = new List<string> { clientID, clientSecret, tenantID };
if (clientID == null)
throw new Exception("ShareAppSettings.Debug.Config file was not provided in this repo.");
return (appCred);
}
For some reason I am not getting values for clientId, slientSecret nor tenantId. This code is a part of grasshopper Add-on for v6 template, and its running on .NET Framework 4.7.1. Whenever I copy the same code into a new C# console of a same framework, the code is built. I would truly appreciate if you could give me suggestions on how to solve this.
What "EnableWindowsFormsHighDpiAutoResizing" means and how can make this work?
Many Thanks
enter image description here
I suggest to use the file attribute (corresponding to the AppSettingsSection.File property) instead of the configSource attribute (corresponding to the SectionInformation.ConfigSource property) in the appSettings section.
configSource doesn't support other keys in the section, while appSettings may contain other keys, needed by the Application and possibly somewhere else (someone else may add/remove them - for testing purposes or any other reason).
The file attribute allows instead the presence of other key in the appSettings section.
Your app.config file can be:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings file="ShareAppSettings.debug.config">
<add key="DpiAwareness" value="PerMonitorV2"/>
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
</startup>
</configuration>
Now the values are accessible by both opening a named configuration section:
appSettings.Settings[] returns a KeyValueConfigurationElement
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
AppSettingsSection appSettings = (AppSettingsSection)config.GetSection("appSettings");
var kvpClientID = appSettings.Settings["clientID"];
var kvpClientSecret = appSettings.Settings["clientSecret"];
var kvpCenantID = appSettings.Settings["tenantID"];
string clientID = kvpClientID.Value;
and directly, using ConfigurationManager.AppSettings - a NameValueCollection - which returns the value of the specified key:
string clientID = ConfigurationManager.AppSettings["clientID"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
string tenantID = ConfigurationManager.AppSettings["tenantID"];
As a note, using the file attribute, your ShareAppSettings.debug.config doesn't need (but it's not forbidden) the XML header, it can be just:
<appSettings>
<add key="clientID" value="11" />
<add key="clientSecret" value="11" />
<add key="tenantID" value="11" />
</appSettings>
Secondary note:
you can set the file attribute to point to another file at run-time and refresh the appSettings values to updated the configuration.
Note that, if a file attribute was already set, all values contained in that .config file are not dismissed, but instead moved to the [Application].exe.config file, to become part of the <appSettings> section (thus, they are preserved).
Another reason why using the file attribute may be preferable.
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var appSettings = config.AppSettings;
appSettings.File = "SomeOtherFile.config";
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");

Log4net is not writing to file

I followed youtube videos and articles on net and implemented this. But it never writes to my log file. Tried with all suggestions around many forums with no use.
not sure where I went wrong. I had this inside class library.
app.config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<log4net><appender name="myLogAppender" type="log4net.Appender.RollingFileAppender" >
<file value="D:\\Log4NetLog.txt" /><layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level - %message%n" /></layout></appender>
<logger name="myLog"><level value="ALL"></level><appender-ref ="myLogAppender" />
</logger></log4net></configuration>
and in the Assembly.info.cs:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "app.config", Watch = true)]
and in the class file:
ILog mylog = LogManager.GetLogger("myLog");
string xx = "tokensalt";
mylog.Info(xx);
If you configuration is in you app.config, you do not need to specify the file in the Configurator:
[assembly: log4net.Config.XmlConfigurator()]
Also the watch is not very usefull, when you change the app.config file. The applpication will restart anyway and the file will be reloaded.
If that is not working, I would guess that the path you logging to is not accessible by the web user you are logging with.
->>> <file value="D:\\Log4NetLog.txt"
Make sure you choose a path where you have access.
Use the file appender and not the rolling appender, the rolling appender was made for backup purposes, for example if your file exceeds 10mb then it will write to your rolling appender and you can decide how many files of 10mb you write there, from the log4net site:
RollingFileAppender can roll log files based on size or date or both
depending on the setting of the RollingStyle property. When set to
Size the log file will be rolled once its size exceeds the
MaximumFileSize. When set to Date the log file will be rolled once the
date boundary specified in the DatePattern property is crossed. When
set to Composite the log file will be rolled once the date boundary
specified in the DatePattern property is crossed, but within a date
boundary the file will also be rolled once its size exceeds the
MaximumFileSize. When set to Once the log file will be rolled when the
appender is configured. This effectively means that the log file can
be rolled once per program execution.
Here is a working web.config example that should work for you:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="FileAppender" type="log4net.appender.FileAppender">
<file value="C:\MyLogs\MyLogFile.txt"/>
<appendToFile value="true"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{ABSOLUTE} [%logger] %level - %message%newline%exception"/>
</layout>
</appender>
<root>
<level value="DEBUG"></level>
<appender-ref ref="FileAppender"></appender-ref>
</root>
</log4net>

How do I read a custom section in app.config from codebehind?

I have an app.config file that stores values in a few different sections. I have these snippets:
<configuration>
<configSections>
<sectionGroup name="someDataAccessLayer">
<section name="databaseConnectionStrings" type="sometype" />
</sectionGroup>
</configSections>
<someDataAccessLayer>
<databaseConnectionStrings>
<databaseConnectionString name="someSQL"
value="database=somedatabase;Integrated Security=False;User Id=sa;server=someserver;Password=somepassword/>
</databaseConnectionStrings>
</someDataAccessLayer>
How do I read the connection string in the codebehind? Specifically the value which is
database=somedatabase;Integrated Security=False;User Id=sa;server=someserver;Password=somepassword
Thanks for your help! Please let me know if the question is still unclear.
Your configuration section will be associated with some .NET class to handle it:
<configSections>
<sectionGroup name="someDataAccessLayer">
<section name="databaseConnectionStrings" type="sometype" />
</sectionGroup>
</configSections>
So to read the settings from the <localeSettings> section, you need to use the ConfigurationManager (add a reference to System.Configuration to your project) to get those settings into an instance of that class:
sometype cs = ConfigurationManager.GetSection("someDataAccessLayer/databaseConnectionStrings") as sometype;
Now you have an object of type sometype that contains all the settings in that config section. One of those properties will be a list of database connection strings, which you can now enumerate and find the appropriate one and read it's .Value property.
App.Config Settings:
<configuration>
<configSections>
</configSections>
<connectionStrings>
<add name="MyApp.LocalConnectionString"
connectionString="Data Source= .\SQLEXPRESS;Initial Catalog=DBName;Integrated Security = true"
providerName="System.Data.SqlClient" />
Access at DataLayer using the ConfigurationManager as:
// add reference
using System.Configuration;
// then access connection string in your class
private static string strConnectionString = ConfigurationManager.ConnectionStrings["MyApp.LocalConnectionString"].ConnectionString;

Resources