How to Save to Roaming Profile using ConfigurationManager in C# - c#

I'm trying to save a string to the AppSettingsSection of the current application's default configuration in the roaming profile using ConfigurationManager (ConfigurationUserLevel.PerUserRoaming).
When I'm saving to the local profile (ConfigurationUserLevel.None) it works just fine.
// Write Name in NameSaved Section of AppSettings
public void WriteNameToAppSettings(string nameToSave)
{
// Open Config File
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoaming); // ConfigurationUserLevel.None (local) is working just fine...
// Add or Update NameSaved Section of AppSettings
if ((configuration.AppSettings.Settings["NameSaved"]?.Value) == null)
configuration.AppSettings.Settings.Add("NameSaved", nameToSave);
else
configuration.AppSettings.Settings["NameSaved"].Value = nameToSave;
// Save and Refresh Config File
configuration.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(configuration.AppSettings.SectionInformation.Name);
}
// Set LastEnteredName Property from NameSaved Section of AppSettings
public void ReadNameFromAppSettings()
{
// Read Config File and then Get Name LastEntered Section of AppSettings
LastEnteredName = ConfigurationManager.AppSettings["NameSaved"]?.ToString() ?? ""; // If null default to ""
}
The error I'm getting is:
System.InvalidOperationException: 'ConfigurationSection properties cannot be edited when locked.'
Any clues on how to fix this?

Related

Exception : System.InvalidOperationException: An unexpected error occurred in 'ClientConfigurationHost::Init'

I am trying to read the custom-defined configuration file from the library project that I have created in c#.
To read the configuration file, There is a ConfigManager i have created as below,
static Configuration ConfigManager
{
get
{
if (_configuration == null)
{
//Map the new configuration file.
ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap();
configFileMap.ExeConfigFilename = _assemblyLocation;
// Get the mapped configuration file
_configuration = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
}
return _configuration;
}
}
I am getting the exception at OpenMappedExeConfiguration() Method.
Any help would be appreciated.
Thanks in advance.

Access denied when attempt Configuration.Save() for installation in Program Files

Attempts to use Configuration.Save() fail when the WPF program is installed under "Program Files". If installed elsewhere, the Save() works as expected. Isn't the program itself authorized to edit its own .config file?
I get two exceptions:
System.Configuration: An error occurred loading a configuration file: Access to the path 'C:\Program Files\Advanced Applications\ConfigurationTest\ejoqasrr.tmp' is denied. (C:\Program Files\Advanced Applications\ConfigurationTest\WPF.exe.Config)
mscorlib: Access to the path 'C:\Program Files\Advanced Applications\ConfigurationTest\ejoqasrr.tmp' is denied.
I tried opening with ConfigurationUserLevel.PerUserRoaming) instead of ConfigurationUserLevel.None but it still failed, reporting different exceptions:
System.Configuration: An error occurred executing the configuration section handler for appSettings.
System.Configuration: ConfigurationSection properties cannot be edited when locked.
[NOTE: Searching found an article that appears related but didn't provide a resolution for this issue:
Access to path denied for App.Config on Windows 8. How can I update App.Config?
The first two methods are called from MainVM and invoke the underlying base methods which expect to find a correlated property on the passed in object and then synchronize the appropriate values in AppSettings.
private void SettingsLoad()
{
SettingsLoad(this);
}
private void SettingsSave()
{
try
{
SettingsSave(this);
}
catch (Exception ex)
{
currentMessageAction = MessageAction.Acknowledge;
window.MessagePanel.Show("EXCEPTION!", Utility.ParseException(ex));
}
}
....
public static void SettingsLoad(object main)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
foreach (KeyValueConfigurationElement setting in config.AppSettings.Settings)
{
// Attempt to get a reference to the property and, if found, set its value
var prop = main.GetType().GetProperty(setting.Key);
if (prop != null)
{
prop.SetValue(main, setting.Value);
}
}
}
public static void SettingsSave(object main)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
foreach (KeyValueConfigurationElement setting in config.AppSettings.Settings)
{
// Attempt to get a reference to the property and, if found, update its value
var prop = main.GetType().GetProperty(setting.Key);
if (prop != null)
{
setting.Value = prop.GetValue(main).ToString();
}
}
// This line produces an exception
config.Save(ConfigurationSaveMode.Modified);
}
Isn't the program itself authorized to edit its own .config file?
No. The user account under which the application is running must have permissons to write to the folder/file.
Apparently it doesn't have the appropriate permissions to write to the "Program Files" folder in your case.
How to Set File and Folder Permissions in Windows

Can I, how do I, supply a settings file to an Azure Function?

When porting an application that uses a settings file to an Azure Function, is it necessary to remove reliance on the file?
I want to write a function app to import data from Xero into an Azure sql database.
The Xero SDK I am using is expecting an appsettings.json file.
Consequently when the function runs I get the error
System.Private.CoreLib: Exception while executing function:
FunctionXeroSync. Xero.Api: The type initializer for
'Xero.Api.Infrastructure.Applications.Private.Core' threw an exception.
Microsoft.Extensions.Configuration.FileExtensions: The configuration file
'appsettings.json' was not found and is not optional. The physical path is
'C:\Users\kirst\AppData\Local\AzureFunctionsTools\Releases\2.6.0\cli\appsettings.json'.
I tried putting the relevant settings in via the Manage Application Settings link on the VS2017 Project Publish Tab. Clearly this fails. Is there another way I can use?
Here is the relevant code in the api. I would prefer not to have to modify it, so that I can use the official nuget package.
namespace Xero.Api
{
public class XeroApiSettings : IXeroApiSettings
{
public IConfigurationSection ApiSettings { get; set; }
public XeroApiSettings(string settingspath)
{
var builder = new ConfigurationBuilder()
.AddJsonFile(settingspath)
.Build();
ApiSettings = builder.GetSection("XeroApi");
}
public XeroApiSettings() : this("appsettings.json")
{
}
public string BaseUrl => ApiSettings["BaseUrl"];
public string CallbackUrl => ApiSettings["CallbackUrl"];
public string ConsumerKey => ApiSettings["ConsumerKey"];
public string ConsumerSecret => ApiSettings["ConsumerSecret"];
public string SigningCertificatePath => ApiSettings["SigningCertPath"];
public string SigningCertificatePassword => ApiSettings["SigningCertPassword"];
public string AppType => ApiSettings["AppType"];
public bool IsPartnerApp => AppType?.Equals("partner", StringComparison.OrdinalIgnoreCase) ?? false;
}
}
When I add
log.LogInformation("base directory: "+AppDomain.CurrentDomain.BaseDirectory);
to the function I get
D:\Program Files (x86)\SiteExtensions\Functions\2.0.12095-alpha\32bit\
when running in the portal
When porting an application that uses a settings file to an Azure Function, is it necessary to remove reliance on the file?
Not necessary, we can still use the settings file required by the application. We only need to make sure the path of settings file is correct.
Put appsettings.json under function project and set it to be copied to output/publish directory.
Add ExecutionContext context in Azure Function method signature, it's used to find current function app directory(where appsettings.json locates).
Pass the valid path of appsettings.json in Azure Function to initialize XeroApiSettings.
var xeroApiSettings = new XeroApiSettings(context.FunctionAppDirectory+"/appsettings.json");
This Jon Gallant's blog suggests that you need to add the optional parameter to the AddJsonFile as it does not exist when you deploy:
var config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
Note that in Azure, this will refer to the 'appsettings.json' file

Relative virtual path is not allowed when using server.MapPath()

I am Trying to get the configuration file using the following code:
public void EncryptConnString()
{
Configuration config = WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Server.MapPath(#"/"));
ConfigurationSection section = config.GetSection("connectionStrings");
if (!section.SectionInformation.IsProtected)
{
config.Save(ConfigurationSaveMode.Modified);
}
}
But i am getting the error
The relative virtual path 'F:/xxxx/yyyy/sample/' is not allowed here.
Note: I am accessing this code in global.asax page What i am doing wrong?
If you pass null to this method, it will return the root config file for you:
var config = WebConfigurationManager.OpenWebConfiguration(null);

Encryption in DATA access block

I am using enterprise library DATA access block in my application and now I want to encrypt the connection string and store it in the config file and consume it in my application after decrypting the same.
How can I do this?
You can encrypt sections of your web.config using DPAPI provider. Nothing else need to change in your application. you still keep reading appsettings and conn. strings as usual.
//call: ProtectSection("appSettings","DataProtectionConfigurationProvider");
private void ProtectSection(string sectionName, string provider)
{
Configuration config =
WebConfigurationManager.
OpenWebConfiguration(Request.ApplicationPath);
ConfigurationSection section = config.GetSection(sectionName);
if (section != null && !section.SectionInformation.IsProtected)
{
section.SectionInformation.ProtectSection(provider);
config.Save();
}
}
//call: UnProtectSection("appSettings");
private void UnProtectSection(string sectionName)
{
Configuration config =
WebConfigurationManager.
OpenWebConfiguration(Request.ApplicationPath);
ConfigurationSection section = config.GetSection(sectionName);
if (section != null && section.SectionInformation.IsProtected)
{
section.SectionInformation.UnprotectSection();
config.Save();
}
}

Categories

Resources