I have an Windows Forms application VS 2008 - C#, that uses app.config.
In execution time, in Menu option of my application, I want editing values of app.config, save it and restart application.
any sample source code, any good patterns and practices ??
edit:
in MSDN Forums, Jean Paul VA:
Create an test windows forms application and add an app.config into it.
Add reference to System.confguration
Add a key named "font" in appSettings with value "Verdana"
Place a button on form and on click of it add the modification code.
System.Configuration.Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
configuration.AppSettings.Settings.Remove("font");
configuration.AppSettings.Settings.Add("font", "Calibri");
configuration.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
what you think about it ?
I don't think you can actually write to the configuration file at runtime - it may well be read-only, however, there may be a way around this by re-writing the file (with proper alterations as required) and essentially replacing the existing one, then, further, restarting the application to load the new values (I highly doubt this is desirable and personally would not try to instrument this malarkey).
You may also just consider storing application settings in the settings file which are easily manipulated in this way.
To use settings, first let's assume you have a Settings.settings file (if not then create one: Add Item->Settings File), then we have a setting configured named MyUnicornsName; In order to make a change and persist it you can simply do as follows:
Settings.Default.MyUnicornsName = "Lucifers Spawn";
Settings.Default.Save();
Similarly, to read a setting:
ATextDisplayControl.Text = Settings.Default.MyUnicornsName
In case you don't know, Visual Studio will open the settings editor when you open/double click the settings file in the IDE; using this interface you can add and edit your initial settings and their values, and string is not the only supported value, all primitives can be used, and, as far as I know, any serializable value too.
Is there any reason you can't use the usual auto-gen'd Properties.Settings to store the changing data in a settings file instead? One great thing is that you know what you're changing so you don't even have to restart the application!
Using Settings in C#
Runtime access of settings is as easy as:
this.BackColor = Properties.Settings.Default.myColor;
(There is no good pattern for modifing app.config itself simply b/c it's designed to be readonly in that context, with expert-user settings.)
Use the Project->Properties->Settings for these kinds of things.
well actually the Properties in the App.config are ReadOnly so u cant do it.
But there's a trick............................
In the Settings.cs file create a Function or method that is public so that it can be available with Properties.settings
and write the following code..
public void ChangeProperty(string propertyname, string value)
{
this[propertyname] = value;
}
remember to pass the exact string of the property name to the method. or better create a Writeonly Property for the setting.
update
here is a code for setting as a property, i am taking a connection string as an example, bet it can be anything. remember the property stored is of Object type so you can create property specific to that..
public string MyCustomConnectionstring
{
set
{
//replace the string with your connection string otr what ever setting you want to change
this["myConnectionString"] = value;
}
}
Now you can easily use this Property to change the ConnectionString at run time...
Related
I'm currently working on a dll which would be used across future projects, and trying to fill it with every useful method developped in the last one. One of these methods that i'd like to re-use allows to generate an excel file with any object collection, and uses a resx resource file to get the column headers based on the object's property names.
Now, my problem is that I can't access or even check the existence of such a file from the library. A possible workaround would be to turn this resource file into a dictionary and pass it as a parameter, but I didn't find a way to do so or any documentation on the subject. Any hint or suggestion about this ?
Thank you for helping me here...
P.S. : I'm working with Visual Studio 2013, in case that could be relevant.
Here's a workaround I found and which allows to get a "RuntimeResourceSet" object, which is structurally close to a dictionnary (and which could be easily turned into one, if you specifically need a dictionnary) :
var myResourceSet = MyResource.ResourceManager.GetResourceSet(CultureInfo.CurrentCulture, true, true);
Then, you can get the set's items this way :
var myString = myResourceSet.GetString("MyKey");
Hope that will help !
I am using 2 separators, and I re-create the dictionary by using split:
Dictionary<string, string> MyDictionary = Resource.MyResourceNme.Split(',').ToDictionary(x => x.Split('|')[0], x => x.Split('|')[1]);
MyResource would look like:
AUD|SYD,GBP|LON,JPY|TOK
Maybe there is a more efficient way of doing it (I don't like using twice the second split).
I am working on an Application which has multiple projects in it. Lets just consider two for now ProjectCore and ProjectUI.
I need to share Application settings between these projects. What i did was, created Settings file at Solution level and add those settings as link in these projects (Add Existing Item -> Add as Link).
ProjectUI has some UIControls that are bind to Settings.Default's different Settings. And ProjectCore sets value to Settings.Default as well.
Now if i use each project's Settings instance from Settings.Designer, they will be two different instances. So binding will not work if i set some value from ProjectCore.
ProjectUI depends on ProjectCore, so i can not just add Settings in ProjectUI and write a wrapper in ProjectUI and use that to set value from ProjectCore. This will create circular dependency.
Now how can i share and Settings file and keep the binding working for ProjectUI?
Hope it may help you, I just create a sample in which i took two projects as you said, then i add setting to core project and change its access modifier to public and give its reference to UI, now i can access those setting in my UI project.
for. e.g.
test.Settings1.Default.SettingTest = "test";
here test is namespace, Setting1 is class and Default is static instance of Setting1 class.
SettingTest is my setting of type string. Though SettingTest is read-only i change its definition in desginer.cs to
public string SettingTest {
get {
return ((string)(this["SettingTest"]));
}
set {
this["SettingTest"] = value;
}
}
Does anyone know how to pass the sfx settings for the SevenZipSfx class located at http://sevenzipsharp.codeplex.com/. I need to specify what file to run, etc. I just took one of the samples e.g
;!#Install#!UTF-8!
RunProgram="setup.exe /s"
GUIMode="2"
;!#InstallEnd#!
and set it via the sfx.ModuleFileName property but its fails with null exception when I call the
sfx.MakeSfx(#"C:\a.7z", #"C:\test.exe"); inside the GetSettingsStream(...) as the settings.key is null
I don't think this is the correct way but can't seem to locate where its reading the settings from. I don't want to hard code this in the source.
I am trying to get started in Visual Studio (2010) extensions and I am having a hard time finding the right materials. I have the SDK, but the included samples seem to be things like adorners, windows, and icons.
I am trying to make an extension that will work directly with the text editor (to alphabetize all of my method names in a class, or make all constant names upper case for example) but I can't find a demo for this type of functionality, or even a tutorial.
Does anyone know where I can find this kind of stuff?
I had the exact same question and now have browsed the web several hours until I was being able to understand and explain how you'd need to start with such an extension.
In my following example we will create a small and dumb extension which will always add "Hello" to the beginning of a code file when an edit has been made. It's very basic but should give you an idea how to continue developing this thing.
Be warned: You have to parse the code files completely on your own - Visual Studio does not give you any information about where classes, methods or whatever are and what they contain. That's the biggest hurdle to be taken when doing a code formatting tool and will not be covered in this answer.[*]
For those who skipped to this answer, make sure you downloaded and installed the Visual Studio SDK first or you will not find the project type mentioned in step one.
Creating the project
Start by creating a new project of the type "Visual C# > Extensibility > VSIX Project" (only visible if you selected .NET Framework 4 as the target framework). Please note that you may have to select the "Editor Classifier" project type instead of the "VSIX Project" type to get it working, s. comment below.
After the project has been created, the "source.extension.vsixmanifest" file will be opened, giving you the ability to set up product name, author, version, description, icon and so on. I think this step is pretty self-explaining, you can close the tab now and restore it later by opening the vsixmanifest file.
Creating a listener class to get notified about text editor instance creations
Next, we need to listen whenever a text editor has been created in Visual Studio and bind our code formatting tool to it. A text editor in VS2010 is an instance of IWpfTextView.
Add a new class to our project and name it TextViewCreationListener. This class has to implement the Microsoft.VisualStudio.Text.Editor.IWpfTextViewCreationListener interface. You need to add a reference to Microsoft.VisualStudio.Text.UI.Wpf to your project. The assembly DLL is found in your Visual Studio SDK directory under VisualStudioIntegration\Common\Assemblies\v4.0.
You have to implement the TextViewCreated method of the interface. This method has a parameter specifying the instance of the text editor which has been created. We will create a new code formatting class which this instance is passed to later on.
We need to make the TextViewCreationListener class visible to Visual Studio by specifying the attribute [Export(typeof(IWpfTextViewCreationListener))]. Add a reference to System.ComponentModel.Composition to your project for the Export attribute.
Additionally, we need to specify with which types of files the code formatter should be bound to the text editor. We only like to format code files and not plain text files, so we add the attribute [ContentType("code")] to the listener class. You have to add a reference to Microsoft.VisualStudio.CoreUtility to your project for this.
Also, we only want to change editable code and not the colors or adornments around it (as seen in the example projects), so we add the attribute [TextViewRole(PredefinedTextViewRoles.Editable)] to the class. Again you need a new reference, this time to Microsoft.VisualStudio.Text.UI.
Mark the class as internal sealed. At least that's my recommendation. Now your class should look similar to this:
[ContentType("code")]
[Export(typeof(IWpfTextViewCreationListener))]
[TextViewRole(PredefinedTextViewRoles.Editable)]
internal sealed class TextViewCreationListener : IWpfTextViewCreationListener
{
public void TextViewCreated(IWpfTextView textView)
{
}
}
Creating a class for code formatting
Next, we need a class handling the code formatting logic, sorting methods and so on. Again, in this example it will simply add "Hello" to the start of the file whenever an edit has been made.
Add a new class called Formatter to your project.
Add a constructor which takes one IWpfTextView argument. Remember that we wanted to pass the created editor instance to this formatting class in the TextViewCreated method of our listener class (simply add new Formatter(textView); to the method there).
Save the passed instance in a member variable. It'll become handy when formatting the code later on (e.g. for retrieving the caret position). Also tie up the Changed and PostChanged events of the TextBuffer property of the editor instance:
public Formatter(IWpfTextView view)
{
_view = view;
_view.TextBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(TextBuffer_Changed);
_view.TextBuffer.PostChanged += new EventHandler(TextBuffer_PostChanged);
}
The Changed event is called every time an edit has been made (e.g. typing a char, pasting code or programmatical changes). Because it also reacts on programmatical changes I use a bool determining if our extension or the user / anything else is changing the code at the moment and call my custom FormatCode() method only if our extension is not already editing. Otherwise you'll recursively call this method which would crash Visual Studio:
private void TextBuffer_Changed(object sender, TextContentChangedEventArgs e)
{
if (!_isChangingText)
{
_isChangingText = true;
FormatCode(e);
}
}
We have to reset this bool member variable in the PostChanged event handler again to false.
Let's pass the event args of the Changed event to our custom FormatCode method because they contain what has changed between the last edit and now. Those edits are stored in the array e.Changes of the type INormalizedTextChangeCollection (s. the link at the end of my post for more information about this type). We loop through all those edits and call our custom HandleChange method with the new text which this edit has produced.
private void FormatCode(TextContentChangedEventArgs e)
{
if (e.Changes != null)
{
for (int i = 0; i < e.Changes.Count; i++)
{
HandleChange(e.Changes[0].NewText);
}
}
}
In the HandleChange method we could actually scan for keywords to handle those in a specific way (remember, you have to parse any code on yourself!) - but here we just dumbly add "Hello" to the start of the file for testing purposes. E.g. we have to change the TextBuffer of our editor instance. To do so, we need to create an ITextEdit object with which we can manipulate text and apply it's changes afterwards. The code is pretty self-explaining:
private void HandleChange(string newText)
{
ITextEdit edit = _view.TextBuffer.CreateEdit();
edit.Insert(0, "Hello");
edit.Apply();
}
When compiling this add-in, an experimental hive of Visual Studio starts up with only our extension loaded. Create a new C# file and start typing to see the results.
I hope this gives you some ideas how to continue in this topic. I have to explore it myself now.
I highly recommend the documentation of the text model of the editor on MSDN to get hints about how you could do this and that.
http://msdn.microsoft.com/en-us/library/dd885240.aspx#textmodel
Footnotes
[*] Note that Visual Studio 2015 or newer come with the Rosyln Compiler Platform, which indeed already analyzes C# and VB.NET files for you (and probably other pre-installed languages too) and exposes their hierarchical syntactical structure, but I'm not an expert in this topic yet to give an answer on how to use these new services. The basic progress of starting an editor extension stays the same as described in this answer anyway. Be aware that - if you use these services - you will become dependent on Visual Studio 2015+, and the extension will not work in earlier versions.
just have a look at the "Getting started with Editor extensions" site on the MSDN http://msdn.microsoft.com/en-us/library/dd885122.aspx
Thorsten
I have an application that uses SQLite, which is extremely light weight and quick. I have some preferences that don't necessarily need to be loaded on startup, but might need to be used at various times depending on where the user goes. That being said, I can't decide where to store this information.
Q1: Should I just go ahead and store it in the database? Should I store it in a config file?
Q2: Should I load and store the preferences and other data at startup even if they're not necessarily being used right away? Or should I just query the database when I need them?
Example: My application can store the company information for the company that is using the software. Company name, company phone, etc. The only time this information is used is when the software auto-prints a letter, or the user goes to edit their company information in the program.
EDIT: I've realized that this comes down to application settings vs user settings. My program does not have multiple users per copy of the software. That being said, I would suppose these would be application settings.
What you may want to do is write a class that encapsulates the settings and then reads them into Hashtable.
You could have a basic GetSetting method that looks up a setting based on a name. If the setting is located in the Hashtable, return the value, otherwise go to the DB to find the setting and then store it in the Hashtable. You can then write separate properties for each setting you want, each calling the GetSetting/SetSetting methods.
This allows you to store the settings in the DB easily, and caches the reads to avoid constantly reading the DB.
public class Settings {
private object SyncRoot = new object();
private System.Collections.Hashtable _cache = new System.Collections.Hashtable();
public T GetSetting<T>(string xPath, T defaultValue)
{
lock (SyncRoot)
{
if (!_cache.ContainsKey(xPath))
{
T val = GetSettingFromDB<T>(xPath, defaultValue);
_cache[xPath] = val;
return val;
}
return (T)_cache[xPath];
}
}
public T GetSettingFromDB<T>(string xPath, T defaultValue)
{
// Read from DB
}
public void SaveSetting<T>(string xPath, T value)
{
lock (SyncRoot)
{
if (_cache.ContainsKey(xPath))
_cache[xPath] = value;
}
SaveSettingToDB<T>(xPath, value);
}
public T SaveSettingToDB<T>(string xPath, T defaultValue)
{
// Read from DB
}
}
Then just create a class with a bunch of properties like this:
public static bool BooleanFeature
{
get { return Settings.GetSetting<bool>("BooleanFeature", true); }
set { Settings.SaveSetting<bool>("BooleanFeature", value); }
}
Now you can do this in your code:
if (Setting.BooleanFeature) {
// Run certain code
else {
// Run other code
}
How many settings are you looking to save? Using the built-in settings feature is pretty painless.
http://msdn.microsoft.com/en-us/library/aa730869.aspx
Storing configuration data in a file is good for light-weight settings that rarely change. Usually you'd do this for settings that are different between development and production and are used to get your application up and running.
After that, everything else is best stored in a database. This gives you the option for good user interfaces to modify the settings, load them when needed, save them during upgrades to your system, be available if you're using multiple front-ends (versus saving the configuration in a file and ensuring all front-ends have the same up-to-date files.)
In addition to JTAs answer I would like to add that I've used 3 methods and they all have their up and down sides.
Storing them in the built-in one
does actually lock them to the
running user. So for instance if
multiple users use your app, there
will be independent settings for
each user. If this is what you want,
pick this one.
Storing them in the database is
useful if you do not want it to be
bound to a user but rather to the
database. Though you cannot change
these settings from outside the app.
I've used a config-class that I
serialize with XML if I need to edit
it with an xml-editor. For instance
this is very useful if you are
running a service.