"Global" XML settings in C# - c#

A settings file is a nice way to access important data anywhere in a program since we can simply say
string dogType = Settings.Default.FavoriteDogType; or Settings.Default.FavoriteDogType = "Chiwawa";
I like this but the file is managed by the computer (stored in user settings). For my application, I would like to allow the user to select there own settings file (stored by them) and use this file for the settings as in
NewWayOfUsingSettings.Load("bobsFavoriteDogInfo.xml");
and then being able to call
string dogType = NewWayOfUsingSettings.FavoriteDogType;
anywhere in the program where "bobsFavoriteDogInfo.xml" would contain the settings to use. (alternatively, Jane could load "JanesBestDog.xml" etc.) Does C# support a simple way to do this?
Thanks!

Related

What is the best way to store some data in VSTO addin?

I have developed one outlook add-in, that has to be On or Off.
to do that i have declared one static variable as shown below,
ThisAddIn.cs
public static bool isAddInOn = false;
RibbonButton.cs
private void btnRibbon_Click(object sender, RibbonControlEventArgs e)
{
if (ThisAddIn.isAddInOn )
{
ThisAddIn.isAddInOn = false;
btnRibbon.Label = "Disabled";
}
else
{
ThisAddIn.isAddInOn = true;
btnRibbon.Label = "Enabled";
}
}
It is working. But the static variable reset again when i close outlook and open it again. That means when i open outlook by default my add-in is in disabled state.
I just want to store that value at some place. so i can check that value when outlook reopened.
Scenario:
1) open outlook
2) Enable add-in by clicking on its logo (that is in ribbon)
3) now close the outlook
4) when i open outlook again it must enabled
so how can i achieve this ?
There are several techniques you can use to achieve this result. For sure your settings must be serialized to some storage/deserialized during startup of add-in.
One of possible solution could be to use registry for that (in this case probably HKCU (Current user, then it will be private for each user using your add-in) and no special permission is needed.
For storing variable:
public void StoreInRegistry(string keyName, string value)
{
RegistryKey rootKey = Registry.CurrentUser;
string registryPath = #"Software\YourCompanyName\YourAddInName";
using (RegistryKey rk = rootKey.CreateSubKey(registryPath))
{
rk.SetValue(keyName, value, RegistryValueKind.String);
}
}
For reading variable:
public string ReadFromRegistry(string keyName, string defaultValue)
{
RegistryKey rootKey = Registry.CurrentUser;
string registryPath = #"Software\YourCompanyName\YourAddInName";
using (RegistryKey rk = rootKey.OpenSubKey(registryPath, false))
{
if (rk == null)
{
return defaultValue;
}
var res = rk.GetValue(keyName, defaultValue);
if (res == null)
{
return defaultValue;
}
return res.ToString();
}
}
Such stored/retrieved variable should be used during add-in initialization to set your properties. So modification could look like:
ThisAddin.cs
public static bool isAddInOn = ReadFromRegistry("MySetting1", "0") == "1";
RibbonButton.cs
private void btnRibbon_Click(object sender, RibbonControlEventArgs e)
{
if (ThisAddIn.isAddInOn )
{
ThisAddIn.isAddInOn = false;
btnRibbon.Label = "Disabled";
}
else
{
ThisAddIn.isAddInOn = true;
btnRibbon.Label = "Enabled";
}
StoreInRegistry("MySetting1", ThisAddIn.isAddInOn ? "1" : "0");
}
Other options could serialization to file - some class with settings serialized to i.e. isolated storage, database (local or central) etc.
I've used several methods over the years to store configuration data for users.
Properties.Settings.Default.Properties, so writing in the application project properties. It's solid, never had an issue with it, for hundreds of users over several years.
Local config files in text, so writing to a known area for the user with fallback. In a stable environment, one can choose the home area for the user, and read/write to the local config file, which also makes it accessible to support if it breaks and needs manual changes. As a fallback, one could write to the local temp folder.
Registry is an option i have not used in this case, but it is likely to be a good choice.
Performance is likely a key concern considering it will impact the UI for users. Another concern is ease of use for the developer. For both, my choice would be setting it in the application's properties, where reading and writing is very simple and handled within code, and likely very fast.
Write
Properties.Settings.Default.PropertyName = propertValue;
Read
var propertValue = Properties.Settings.Default.PropertyName;
2018 UPDATED ANSWER
The recommended way to achieve this is now to use the already configured settings files in your project's properties. These files are auto-generated when create your project :
And open the following window when clicked :
You can access your settings value programmatically into Properties.Settings.Default.Properties anywhere.
The header bar at the top of the Settings page contains several controls:
Synchronize
Synchronize restores user-scoped settings that the application uses at run time or during debugging to their default values as defined at design time. To restore the data, remove run-time generated application-specific files from disk, not from project data.
Load Web Settings
Load Web Settings displays a Login dialog box that enables you to load settings for an authenticated user or for anonymous users. This button is enabled only when you've enabled client application services on the Services page and specified a Web settings service location.
View Code
For C# projects, the View Code button enables you to view the code in the Settings.cs file. This file defines the Settings class, which enables you to handle specific events on the Settings object. In languages other than Visual Basic, you must explicitly call the Save method of this wrapper class in order to persist the user settings. You usually do this in the Closing event handler of the main form. Following is an example of a call to the Save method:
C#
Properties.Settings.Default.Save();
For Visual Basic projects, the View Code button enables you to view the code in the Settings.vb file. This file defines the MySettings class, which enables you to handle specific events on the My.Settings object. For more information about accessing application settings by using the My.Settings object, see Access application settings.
For more information about accessing application settings, see Application settings for Windows Forms.
Access modifier
The Access modifier button specifies the access level of the Properties.Settings (in C#) or My.Settings (in Visual Basic) helper classes that Visual Studio generates in Settings.Designer.cs or Settings.Designer.vb.
For Visual C# projects, the access modifier can be Internal or Public.
For Visual Basic projects, the access modifier can be Friend or Public.
By default, the setting is Internal in C# and Friend in Visual Basic. When Visual Studio generates helper classes as Internal or Friend, executable (.exe) applications cannot access the resources and settings that you have added to class libraries (.dll files). If you have to share resources and settings from a class library, set the access modifier to Public.
For more information about the settings helper classes, see Manage application settings.
Settings grid
Settings Grid is used to configure application settings. This grid includes the following columns:
Name
Enter the name of the application setting in this field.
Type
Use the drop-down list to select a type for the setting. The most frequently used types appear in the drop-down list, for example, String, (Connection string), and System.Drawing.Font. You can choose another type by selecting Browse at the end of the list, and then selecting a type from the Select a Type dialog box. After you choose a type, it's added to the common types in the drop-down list (for the current solution only).
Scope
Select either Application or User.
Application-scoped settings, such as connection strings, are associated with the application. Users can't change application-scoped settings at run time.
User-scoped settings, such as system fonts, are intended to be used for user preferences. Users can change them at run time.
Value
The data or value associated with the application setting. For example, if the setting is a font, its value could be Verdana, 9.75pt, style=Bold.
Documentation link
Reading settings
Writing settings
Settings can be stored as a hidden (associated) item in a folder, such as the Inbox or the Calendar folder. For example, Outlook stores the list of categories as a hidden item in the Calendar folder. POP3 message ids are stored in a hidden item in the Inbox. The advantage of the hidden items is the roaming capability - Exchange mailbox user can see the data from any computer.
You can see the hidden items in OutlookSpy (I am its author) - click IMAPIFolder button, go to the "Associated Contents" tab.
Programmatically, such items can be accessed using MAPIFolder.GetStorage in the Outlook Object Model.

What is the appropriate way to load WinForms settings to GUI

I am building an application, which has a form where the user can configure all his settings. When the application is loaded, the previously configured settings should reflect to the GUI (The UI should be consistent to the saved settings).
What I am currently doing is creating the settings on the project properties and I have a LoadSettings() method, which gets the values and outputs them to each component on the UI.
The thing is that this is getting VERY messy, and I don't like it at all.
So, that got me wondering, what are the correct approaches to achieve what I want, but yet getting high quality code? Any patterns for that?
private void LoadConfigs()
{
checkBoxStartOnStartup.Checked = ExistKeyValue(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "Wallbase Downloader");
checkBoxCheckWallbaseOnline.Checked = Settings.Default.CheckWallbaseOnlineStartup;
comboBoxResolution.SelectedIndex = comboBoxResolution.FindStringExact(Settings.Default.Resolution == string.Empty
? GetScreenResolution()
: Settings.Default.Resolution);
comboBoxCondition.SelectedIndex = Settings.Default.ConditionIndex;
textBoxWallpaperFolders.Text = Settings.Default.WallpaperFolder;
numericChangeInterval.Text = Convert.ToString(Settings.Default.ChangeIntervalValue);
comboBoxChangeInterval.SelectedIndex = Settings.Default.ChangeIntervalIndex;
numericCheckInterval.Text = Convert.ToString(Settings.Default.CheckIntervalValue);
comboBoxCheckInterval.SelectedIndex = Settings.Default.CheckIntervalIndex;
numericWallpapersToLookFor.Text = Settings.Default.WallpapersToLookFor.ToString();
}
Well, WinForms are not the cleanest framework around...
What you could do is to load all settings when your application starts up and store them in some storage that is available to all forms, e.g. in a static property in a helper settings class.
You can then access that static property from each form when it loads and make all necessary changes to the form based on the settings.
You can use a Hashtable and use English strings for key to make your code really readable. Then serialize it to file on exit and deserialize it back when application loads. Save the serialized file to some common location so that you do not lose it.

Constant save file directory

I have a VS2012 in C# solution with 4 projects in 4 layer structure(Presentation, BusinessLogic, DomainModel, DataAccess) and wanted to give the user the option to select the database's file's path at the Login form, which is in the Presentation layer (it is then used when a creating connection to the Database in a static method in the DataAccess layer). And the path would be saved and used the next time the application runs.
A bit more workflow example would be:
User starts the application and the login form appears;
User chooses the Database's file path with a FolderBrowserDialog or
OpenDirectoryDialog;
User works on the application then ends it;
User starts the application and the Database's file path is the one
he picked before;
User works on the application then ends it;
User starts the application and picks another file;
User works on the application then ends it;
User starts the application and the Database's file path is the one
he picked before.
Codewise I don't want to go passing along that string (path) all around my code for each method that needs to create a connection and such.
So any ideas on how to directly save it in the method that's directly using it? If not only when the user wants to change it then just forcing the user to pick the file when the starts the application.
Currently what I'm doing is forcing the user to put the file he wants in the solution's directory with a specific name before starting the application when he wants to use another Database file. For that I'm using:
public static string path;
public static OleDbConnection createConnection()
{
path = DirProject() + "\\Calibrações Equipamentos ULSM.accdb";
OleDbConnectionStringBuilder builder = new OleDbConnectionStringBuilder();
builder["Provider"] = "Microsoft.ACE.OLEDB.12.0";
builder["Data Source"] = path;
return new OleDbConnection(builder.ConnectionString);
}
private static string DirProject()
{
string DirDebug = System.IO.Directory.GetCurrentDirectory();
string DirProject = DirDebug;
for (int counter_slash = 0; counter_slash < 3; counter_slash++)
{
DirProject = DirProject.Substring(0, DirProject.LastIndexOf(#"\"));
}
return DirProject;
}
Configuration (=data) is not saved into a method (=code). It's usually saved into a configuration file. You can leverage .NET's application and user settings mechanism to achieve what you want.
Use User Settings
How To: Write User Settings at Run Time with C#
How To: Read Settings at Run Time With C#

Get and Set values in local resource file

I have put 2 strings in the built-in resource file of my main project (not sure how I define this properly). How can I access these values? How would I change them? The resource is public so that the user can change them.
eg:
Project1.Resources.Get("string1").Value();
and
Project1.Resources.Set("string1") = "whatever";
This is pseudo code.
Resources are not intended to be changed at runtime. You should consider using user settings instead. For details, see Using Application Settings and User Settings on MSDN.
This will allow you to use the designer to build the settings, and write:
string string1 = Properties.Settings.Default.String1;
And:
Properties.Settings.Default.String1 = "whatever";
Properties.Settings.Default.Save();
You can get resource by writing the following piece of code
Project1.Resources.String1
You can not change it at runtime.

file access in C# program called by PHP

This is the context: I've got to write a source for an intranet site which allows users to import a csv file into MySQL database.
This import is very massive that's why I wrote a C# program.
This program creates some thread which reads some lines of my csv file.
These thread control, change type and insert my data into MySQL database with SQL like this:
insert into table1 (fields) values (dataline 1 ), (data line 25),...,(data line n);
This request exists for 9 tables.
This program can be used by everyone because the source code is dynamic : example to insert data I write a dictionary which contain my 9 tables with all fields, types and the CSV header of the import file (which contains some accent and symbol, I've to change it because I can't put them into fieldname in my database).
This dictionary can be create only with a file called MAP.csv
Example:
table / field / type / header
table 1 / field1_table1 /string / hêàder
table 1 / field2_table1/ int / header1
table 2 / field1_table2/ date / hêàder2
table 1 / field3_table1/ string / hêàder3
My C# program works very well when I execute the program.exe
But when I call it with php with exec("programpath.exe parameter1 parameter2",return,otherreturn) function this program can't work.
In fact when I try to access to externfile like config.xml , MAP.csv, otherfile.txt/csv/.. with my c# program. The execution stop and there is a windows error which says "program.exe stop its work" ( program.exe à cessé de fonctionner in French).
So I try to write my problem simply: when I try to access into a file with my c# program called by php, there is a window problem which stop the traitment.
EDIT :
I found the solution, I just have to do a cd c:/path_program/
In fact when I start my website the current folder is not c:/ but the folder in which Symfony starts...
Was just a beginner error.
Could be a permission problem.
The Webserver is running under a certain security context (user). Depending on the used Webserver (IIS, apache, ...) and its configuration.
As you execute an application out of your PHP it will run under the same "User" as your WebServer.
You said that it seems as your application crashes as soon as an external file gets accessed --> very possible the user which executes the website has access to run the exe but no access for the configuration file.
you use relative paths to access the file:
to map the relative to the application path to an absolute path you can use this snippet:
string appPath = System.Windows.Application.ResourceAssembly.Location;
string relativeResourcePath = "RESSOURCES/file.csv";
string absolutePath = System.IO.Path.Combine(appPath, relativeResourcePath);
Check Edit post for the solution

Categories

Resources