I'm working on an winform application, where I store some setting (username, email, zipcode) in the app.config file.
public static void Set(string key, string value)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var entry = config.AppSettings.Settings[key];
if (entry == null)
config.AppSettings.Settings.Add(key, value);
else
config.AppSettings.Settings[key].Value = value;
config.Save(ConfigurationSaveMode.Modified);
}
I'd like to save the settings to the app.config file. So I have this code.
Problem is: I can only use the variable key once.... So i can't saven the email and zipcode.
I was thinking of working with an array, but I have no idea on how to implement this. Any suggestions?
private void button_savesettings_Click(object sender, EventArgs e)
{
string key = "username";
string username = textBox_user.Text;
Set(key, username);
}
Many thanks!
A simple loop will solve the problem
void SetAppSettingsValues(Dictionary<string, string> dict)
{
// bit of validation
if (dict == null || !dict.Any())
return;
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
foreach (var key in dict.Keys)
{
var configItem = config.AppSettings.Settings[key];
if (configItem == null)
config.AppSettings.Settings.Add(key, dict[key].Value);
else
config.AppSettings.Settings[key].Value = dict[key].Value;
}
config.Save(ConfigurationSaveMode.Modified);
}
The better way is to use SQLite for Winform.
Saving things to app.config could be messy when your data variable grows bigger.
Related
I am basically reading below registry path,
SOFTWARE\\WOW6432Node\\Microsoft
But I have different sub keys and keys to read.
example
Version under SOFTWARE\\WOW6432Node\\Microsoft\\DataAccess
NodePath9 under SOFTWARE\\WOW6432Node\\Microsoft\\ENROLLMENTS\\ValidNodePaths
etc.
Currently I am able to read it one-by-one, but what are the ways so that I need to go the registry ONLY one time and I can do all other manipulation in C# code?
Can I read all information at once (so that ONLY one call to registry) till SOFTWARE\\WOW6432Node\\Microsoft and do rest work in C# code?
var X1 = GetRegistryValue("SOFTWARE\\WOW6432Node\\Microsoft\\DataAccess", "Version");
var X2 = GetRegistryValue("SOFTWARE\\WOW6432Node\\Microsoft\\ENROLLMENTS\\ValidNodePaths", "NodePath9");
private static string GetRegistryValue(string subKey, string keyName)
{
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(subKey))
{
if (key != null)
{
if (key.GetValue(keyName) != null)
{
return (string)key.GetValue(keyName);
}
}
return null;
}
}
The OpenSubKey() method returns a registry key, so you could create a common one first and then pass it into the GetRegistryValue()...
private static RegistryKey GetCommonKey(string subKey)
{
return Registry.LocalMachine.OpenSubKey(subKey);
}
private static string GetRegistryValue(RegistryKey commonKey, string subKey, string keyName)
{
using (commonKey.OpenSubKey(subKey))
{
if (key != null)
{
if (key.GetValue(keyName) != null)
{
return (string)key.GetValue(keyName);
}
}
return null;
}
}
// usage
var commonKey = GetCommonKey("SOFTWARE\\WOW6432Node\\Microsoft");
var version = GetRegistryValue(commonKey, "DataAccess", "Version");
var nodePath = GetRegistryValue(commonKey, "ENROLLMENTS\\ValidNodePaths", "Version");
Team,
I have this piece of code which invariably ties up itself in a sort of race condition especially when two or more resources are trying to write to eventlog.config file simultaneously. I have googling out several channels but not able to solve this error out. Can anyone help me to modify this code so that i can remove the race condition.
private void UpdateLastEventId(IList<EventLogEntry> entries)
{
if (entries.Count > 0)
{
EventLogEntry lastEntry = entries[entries.Count - 1];
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var configSettings = config.AppSettings.Settings;
string key = string.Format(CultureInfo.InvariantCulture, "{0}|{1}", _eventLogFilter.EventLog, _eventLogFilter.MD5Hash);
if (configSettings[key] == null)
{
configSettings.Add(key, lastEntry.Index.ToString(CultureInfo.InvariantCulture));
}
else
{
configSettings[key].Value = lastEntry.Index.ToString(CultureInfo.InvariantCulture);
}
config.Save(ConfigurationSaveMode.Modified);//Error seems to happen here
}
}
private static readonly object _configLogLock = new object();
private void UpdateLastEventId(IList<EventLogEntry> entries)
{
if (entries.Count > 0)
{
EventLogEntry lastEntry = entries[entries.Count - 1];
lock (_configLogLock)
{
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var configSettings = config.AppSettings.Settings;
string key = string.Format(CultureInfo.InvariantCulture, "{0}|{1}", _eventLogFilter.EventLog, _eventLogFilter.MD5Hash);
if (configSettings[key] == null)
{
configSettings.Add(key, lastEntry.Index.ToString(CultureInfo.InvariantCulture));
}
else
{
configSettings[key].Value = lastEntry.Index.ToString(CultureInfo.InvariantCulture);
}
config.Save(ConfigurationSaveMode.Modified);//Error seems to happen here
}
}
}
I am using C# 4.0. (Winform Application)
I have a code like this:
private bool ChangeEFConnectionString(string connStringName, string newValue)
{
try
{
//CreateXDocument and load configuration file
XDocument doc = XDocument.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
//Find all connection strings
var query1 = from p in doc.Descendants("connectionStrings").Descendants()
select p;
//Go throught each connection string elements find atribute specified by argument and replace its value with newVAlue
foreach (var child in query1)
{
foreach (var atr in child.Attributes())
{
if (atr.Name.LocalName == "name" && atr.Value == connStringName)
if (atr.NextAttribute != null && atr.NextAttribute.Name == "connectionString")
{
// Create the EF connection string from existing
EntityConnectionStringBuilder entityBuilder =
new EntityConnectionStringBuilder(atr.NextAttribute.Value);
//change hte provide conn string
entityBuilder.ProviderConnectionString = newValue;
//back the full connection string to the configuration fiel
atr.NextAttribute.Value = entityBuilder.ToString();
}
}
}
doc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
It works well, but somehow it not work any more.
As I debug it : entityBuilder.ProviderConnectionString = newValue; had the right value
but it still not change the connectionstring.
Use ConfigurationManager for reading and updating connection strings:
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.ConnectionStrings.ConnectionStrings[connStringName].ConnectionString = newValue;
config.Save(ConfigurationSaveMode.Modified, true);
ConfigurationManager.RefreshSection("connectionStrings");
I think all you need is, after the Save, a:
ConfigurationManager.RefreshSection("connectionStrings");
Have you considered giving EF the whole connection string instead of the name? That would keep you from having to modify what the name means at run time.
I try create method for get the connection string value but without value for password, or show password like * character. I need used it in logging.
I use ConnectionStringBuilder for Oracle, SqlServer.
Anyway, another way -better- to implement it ? Maybe more generic . And what it happens it ProviderName is empty...
public static string GetConnectionStringWithouPassword(this ConnectionStringSettings cs)
{
if (cs == null || string.IsNullOrEmpty(cs.ConnectionString)) return null;
if (cs.ProviderName.ToLower().Equals("Oracle.DataAccess.Client".ToLower()))
{
var builderOra = new Oracle.DataAccess.Client.OracleConnectionStringBuilder(cs.ConnectionString);
return "";
}
if (cs.ProviderName.ToLower().Equals("System.Data.SqlClient".ToLower()))
{
var builderSql = new SqlConnectionStringBuilder(cs.ConnectionString);
return "";
}
return null;
}
//
public static string ObtenerCadenasConexion()
{
var sb = new StringBuilder();
ConnectionStringSettingsCollection settings = ConfigurationManager.ConnectionStrings;
if (settings != null)
{
foreach (ConnectionStringSettings cs in settings)
{
sb.AppendLine("Name: " + cs.Name);
sb.AppendLine("ProviderName: " + cs.ProviderName);
sb.AppendLine("ConnectionString: " + cs.GetConnectionStringWithouPassword() + Environment.NewLine);
}
}
return sb.ToString();
}
check this one: DbConnectionStringBuilder Class
you can use the Remove method, no magic parsing required:
for example, from that MSDN page:
static void Main()
{
DbConnectionStringBuilder builder = new
DbConnectionStringBuilder();
builder.ConnectionString =
#"Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\Demo.mdb;" +
"Jet OLEDB:System Database=system.mdw;";
// Try to remove an existing item.
TryRemove(builder, "Provider");
// Try to remove a nonexistent item.
TryRemove(builder, "User ID");
// Try to remove an existing item,
// demonstrating that the search isn't
// case sensitive.
TryRemove(builder, "DATA SOURCE");
Console.ReadLine();
}
static void TryRemove(DbConnectionStringBuilder builder, string itemToRemove)
{
if (builder.Remove(itemToRemove))
{
Console.WriteLine(#"Removed '{0}'", itemToRemove);
}
else
{
Console.WriteLine(#"Unable to remove '{0}'", itemToRemove);
}
Console.WriteLine(builder.ConnectionString);
}
Check the Connection.PersistSecurityInfo property, you may drop this information as soon as the connection is created automatically.
As suggested here, I need to iterate through entries in
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\
to find out the installed path of my application. How to iterate so that I can find out the
InstallLocation value given the DisplayName. How to do it efficiently in C#.
Below is code to achieve your goal:
using Microsoft.Win32;
class Program
{
static void Main(string[] args)
{
RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
foreach (var v in key.GetSubKeyNames())
{
Console.WriteLine(v);
RegistryKey productKey = key.OpenSubKey(v);
if (productKey != null)
{
foreach (var value in productKey.GetValueNames())
{
Console.WriteLine("\tValue:" + value);
// Check for the publisher to ensure it's our product
string keyValue = Convert.ToString(productKey.GetValue("Publisher"));
if (!keyValue.Equals("MyPublisherCompanyName", StringComparison.OrdinalIgnoreCase))
continue;
string productName = Convert.ToString(productKey.GetValue("DisplayName"));
if (!productName.Equals("MyProductName", StringComparison.OrdinalIgnoreCase))
return;
string uninstallPath = Convert.ToString(productKey.GetValue("InstallSource"));
// Do something with this valuable information
}
}
}
Console.ReadLine();
}
}
Edit: See this method for a more comprehensive way to find an Applications Install Path, it demonstrates the using disposing as suggested in the comments.
https://stackoverflow.com/a/26686738/495455
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(#"Whater\The\Key"))
{
if (key != null)
{
foreach (string ValueOfName in key.GetValueNames())
{
try
{
bool Value = bool.Parse((string)key.GetValue(ValueOfName));
}
catch (Exception ex) {}
}
}
}
With a bool cast :D - so the string is expected to be True or False.
For the user registry hive use Registry.CurrentUser instead of Registry.LocalMachine