 |
|
 |
I had a problem retrieving certain colors using the getColor() method, which works fine for some colors but not all. "RosyBrown" for example will not retrieve. I think this problem is the way in which the RES_KnownColorStartString is stripped from the colorString using the string.TrimStart() method.
It seems The TrimStart method does not remove a fixed amount of characters but keeps removing until no match is found, so the string COLOR[RosyBrown] will return "osyBrowm]"
an alternative would be to replace the follow code:
char[] strip = RES_KnownColorStartString.ToCharArray();
//strip
string fString = colorString.TrimStart(strip);
With:
string fString = colorString.Remove(0, RES_KnownColorStartString.Length);
In the following methods: parseKnownColor() and parseUnknownColor()
|
|
|
|
 |
|
 |
Sadly, the email address in the source is dead as well as the url -- my attempts to use it just bounced back.
|
|
|
|
 |
|
 |
Perry,
Are you trying to contact me? I am the one who wrote this library. (a few years ago).
Amber
|
|
|
|
 |
|
 |
Yes, as I mentioned earlier here, the source files seem to have mixed line terminations -- Visual Studio C# reports this error and offers to fix it -- and the url and email in the source both appear to be dead.
I also had some ideas for refactoring and some other stuff, but, OBE I think because:
I was wondering if there was any maintenance effort on the code, but later I saw your comments below suggesting that it was a one-shot, published now and with no maintenance, because you've moved on to other -- hopefully bigger & better -- things than programming.
In that case, thanks for publishing the code.
|
|
|
|
 |
|
 |
Hi Perry,
I am not sure what the deal is with the line terminations. This was written in VS.
I cracked open the download, and yes the source links are no good.
I went to gotdotnet and searched for settingsxpress, and I found the workspace. I was able to log in. In the workspace, there are a few of my ideas for re-factoring, and for future enhancements, as well as some known bugs. I am sure you have many too. I can make that content available here if you want.
The concept of this library was to do everything the microsoft.win32.RegistryKey class library does but with XML. It seemed to me that MS Should have allowed you to read and write to the application config file. That may have changed by now. The other thing is it seemed to me counterintuitive to use the registry for storing settings. .Net is supposed to be drag and drop install/uninstall.
Using a DOM seemed way overkill. So I created this library. I have seen simpler implementations than this, but not as universal and dynamic as this approach. With this approach you can add new settings(or data) at runtime. You do not have a static model.
I wanted to expand on this library in a way that allowed you to create and read any XML data file, in a lean and Agile way.(never got that far) I know I was going to create a version with out the native data types to eliminate the windows.forms reference.
You are more than welcome to take this and run with it. If you want to maintain it go right ahead. Just let me know where to go to check out what you did.
I have moved on, to the world of Macintosh I have not programmed on the .Net framework in two years. But I still think c# rawks!
Amber
|
|
|
|
 |
|
 |
Amber, thank you.
In the end I decided to build my own, but using for inspiration your library, and also SaveSettingsToXml by Kato, and also a short code snippet by someone about how to make a singleline call in a form constructor cause all the text & checkboxes to persist their values.
I decided to put the actual storage off behind a storage provider factory, so that the client code (eg, form) and the settings code neither know where the storage is going, so it can be an orthogonal decision how to actually implement the persistent storage -- much like a cross-cutting aspect I suppose.
Also, I am happily doing some different stuff for my own desires, such as making my actually return an object (which I usually ignore), so that I can catch that object in order to customize behavior by method invocations on it -- and also I made my code that persists TextBox values watch for password boxes and store them via DPAPI, because I don't like plaintext storage of passwords.
So, in short, I'm happy with rolling my own, which is now functioning, and I found a lot of inspiration and education looking over your solution and several others, for which I'm thankful.
|
|
|
|
 |
|
 |
The url in the source here goes to an apparently broken link at gotdotnet.
Instead, try this url:
http://www.gotdotnet.com/workspaces/releases/viewuploads.aspx?id=cd9f2d7e-77bf-4231-b741-41b862f7c587
(However, I cannot post anything there anyway, because Passport goes into an infinite loop and fails to let me log in -- this happens so often I usually give up on any sites requiring Passport.)
|
|
|
|
 |
|
 |
Odd, the source is not formatted for MS-Windows?
I'm looking at what I assume is the main file, SettingsXpress.cs, 99Kb, but it doesn't appear to have consistent line returns?
|
|
|
|
 |
|
 |
I can't get any of the "Delete" methods to work. Before I lose my mind, can anyone post an example of what is working for them, along with the snippet from the xml/config file before the delete? thanks much...
|
|
|
|
 |
|
 |
Let me clarify. Is there a way to delete an outer-most section? For example: <MyAppSettings> <Folders> <HelpFolder Path="Help"/> </Folders> </MyAppSettings> Is there a way to delete the "Folders" section? What I've found I have to do is move it into a subsection, such as: <MyAppSettings> <outer> <Folders> <HelpFolder Path="Help"/> </Folders> </outer> </MyAppSettings> then this will work: SettingsKey TreeViewSettings = SettingsFile.Settings["outer"]; TreeViewSettings.DeleteSettingsKeyTree("Folders"); Otherwise if I do this: SettingsKey TreeViewSettings = SettingsFile.Settings; TreeViewSettings.DeleteSettingsKeyTree("Folders"); I get the error: "The current SettingsKey is the Root SettingsKey or read-only." It isn't intuitive to me to open a key on the outermost "Settings" section and be prohibited from deleting a subsection. Thanks Amber, overall I'm finding your offering useful.
|
|
|
|
 |
|
 |
Mark,
Please relize I havn't programmed in over a year, so my head is really majorly not in this. That said , at first looks it seems like it may be an oversight on my part. I will crack open the code and confirm this, and see if there is a way to make it work the way you want.
Amber Star
Visit My WebLog..
|
|
|
|
 |
|
 |
Please don't go to that extent Amber, I can work around it with no problem. If you've broken free of programming - stay there! I keep threatening to move to the country and open an apple pie stand.
|
|
|
|
 |
|
 |
Just want to say thanks and good job! After finding the read-only nature of the Frameworks config classes usesless, and the MS Component Configuration Application Block a sledgehammer solution, your lib was easy to use and well documented.
|
|
|
|
 |
|
 |
Great article!
How did you do the docs?
In particular, the VS.NET-style HTML
pages are cool.
|
|
|
|
 |
|
 |
I might be asking a dumb question here, but I've tried to create various subkeys with spaces in them with no success... for example, I'd like to maintain user profiles (I see you have shown a simple example) which are identified with a person's name, so I've tried to create a subkey called, for instance, "John Cousins" and store the relevant other information in this section... this fails miserably! Could you enlighten me as to what's happening?
|
|
|
|
 |
|
 |
Hi John,
At this time subkeys cannot contain spaces , as XML elements cannot as well. However it would be easy to add this ability by using the XmlConvert.EncodeName Method and the XmlConvert.DecodeName Method. You have two option you could modify the source code, or Encode and Decode in the client before creating the Subkey.
Also you can join the GotDotNet Workspace and add the feature to the Workspace source code. Or simply post it up as a bug on the workspace, either way, We can get this feature in the library.
Do you have any other questions or suggestions? Feel free to post them on the Workspace.. Your input and insight is very very welcome.
Thank you,
Amber.
Amber Star
Visit My WebLog..
|
|
|
|
 |
|
 |
I've just downloaded it and used it in my project. However there is but a single example of its use. No examples or "cookbook" XML snippets for the more mysterious OpenSubKey(...) and SettingsKey[path] methods. For instance, I would like to know if it can add, modify or delete from the following XML layout: ... <MyAppSettings> <add key="HelpFolder" value="Help" /> <add key="ImagesFolder" value=".\Images" /> <add key="ToolsFolder" value=".\Tools" /> </MyAppSettings> ... Could I use SettingsXpress to pick a particular item based on a key? Thanks for any help, Steve.
|
|
|
|
 |
|
 |
Hi Steve,
First of all thank you for taking the time to ask questions. The only way I know how to improve this article is to get feedback.
Second, I apologize for the lack of examples. This is my very first article, and if there is anything I have learned from posting my first article is, not to rush into it.
Third, I want to make sure that you are aware that there is a help file included in one of the zip file. It is contained in the SettingsXp1.1_lib zip file.
There probably isn't enough examples in the help either. I am working on that.
Now to your questions:
Think of the settings format as Folders and Files.
XML Elements are the folders, Attributes are the files.
That is to say, Element names = SettingsKey names, Attribute names = Settings names.
As with files and folders names must be unique, no duplicates.
The format for the XML Settings file is like this:
<Settings>
<KeyName settingName1="value" settingName2="value">
<SubKeyName settingName1="value" settingName2="value"/>
</KeyName>
</Settings>
So we decided not to use the format you show in your example. Why? Because it is redundant to have Elements called Add. We decided that would creates extra work for the DOM , more data in memory more objects created. It is Inherently known to be Added by it's exsistance.Also because the
file is just more straight forward to read!
The recommended usage for your example would be something like this.
Example A
<MyAppSettings>
<Folders HelpFolder ="Help" ImagesFolder=".\Images" ToolsFolder =".\Tools" />
</MyAppSettings>
Or you can optionally do something like this:
Example B
<MyAppSettings>
<Folders>
<HelpFolder Path="Help"/>
<ImagesFolder Path=".\Images"/>
<ToolsFolder Path=".\Tools"/>
</Folders>
</MyAppSettings>
So a SettingsKey does not have to have settings. It can be simply for structal definition.
Now let's discuss how to access these settings using both examples.
Let's say you want to retrieve the Images folder for example A.
string iPath = SettingsFile.Settings[Folders].GetSetting("ImagesFolder");
Or if you were going to work with many Folder Settings you could create a SettingsKey first. A SettingsKey is like a book marker for a location in the settings file.
SettingsKey folders = SettingsFile.Settings["Folders"];
<br>
string ipath = folders.GetSetting("ImagesFolder");
string hpath = folders.GetSetting("HelpFolder");
string tpath = folders.GetSetting("ToolsFolder");
Let's revisit Example B
Example B
<MyAppSettings>
<Folders>
<HelpFolder Path="Help"/>
<ImagesFolder Path=".\Images"/>
<ToolsFolder Path=".\Tools"/>
</Folders>
</MyAppSettings>
To Retrieve ImagesFolder:
string ipath = SettingsFile.Settings["Folders/ImagesFolder"].GetSetting("Path");
or to work with many folder settings:
SettingsKey folders = SettingsFile.Settings["Folders"];
<br>
string ipath = folders["ImagesFolder"].GetSetting("Path");
string hpath = folders["HelpFolder"].GetSetting("Path");
string tpath = folders["ToolsFolder"].GetSetting("Path");
KeyPoints about CreateSubkey(string path) and SettingsKey[string path]
- they are the exactly the same
- both except a relative path from the current key using '/' as seperator
- both will create the entire path or part of the path if it does not yet exsist(so they always return a SettingsKey.
KeyPoints about OpenSubKey:
- Included to be consistant with the Microsoft.Win32.RegistryKey class
- Can open SubKeys as ReadOnly
- Returns null if subkey does not exsist
- Will not except a path (i.e. "Application/Folders" will not work)
- Only excepts direct childKey names of the current key.
SettingsKey myKey = SettingsFile.Settings.OpenSubKey("Folders");
<br>
SettingsKey myKey = SettingsFile.Settings.OpenSubKey("Folders",true);
OpenSubkey will return null if the key doesn't exsist. But the indexer or the CreateSubKey will actually create all the elements in the path you provide, if they don't exsist.
SettingsKey folders = SettingsFile.Settings.OpenSubKey("Folders",true);
if(folders != null)
{
string iPath = folders.GetSetting("ImagesFolder");
}
<br>
else
{
string iPath = resouces.GetString("DefaultImagesFolder");
SettingsFile.Settings.CreateSubKey("Folders").StoreSetting("ImagesFolder",iPath);
}
Creating a Settings Class using SettingsXpress
Let's look at another example. Suppose we have an application that has different users that log-in to the application. Each user has there own 'profile'. And we want to store there prefrences in the settings file. Okay let's design our settings file.
<Settings>
<Application Name="MyApp" Version="1.0">
<Folders ImagesFolder="./Images" HelpFolder="Help" ToolsFolder="Tools">
<UserSettings>
<Steve AccountType="Manager" StartUpView="DashBoard">
<Folders Data="Steve" BackUp="Steve/Backup"/>
<Options>
<UI TreeViewWidth="150" ShowDailyTips="true" BackColor="Orange">
<BackUp mode="Auto">
</Options>
</Steve>
<Amber AccountType="Programmer" StartUpView="Calender" >
<Folders Data="Amber" BackUp="Amber/Backup"/>
<Options>
<UI TreeViewWidth="100" ShowDailyTips="false" BackColor="Puple">
<BackUp mode="Manual">
</Options>
</Amber>
<DefaultUser AccountType="New" StartUpView="DashBoard">
<Options>
<UI TreeViewWidth="150" ShowDailyTips="true" BackColor="Orange">
<BackUp mode="Auto">
</Options>
</DefaultUser>
</Users>
</Application>
</Settings>
Okay now let's work with our settings file.
public class UserSettings
{
SettingsKey data;
<br>
public void UserSettings(string userName)
{
data = SettingsFile.Settings["Application/UserSettings"].OpenSubkey(userName,true);
<br>
if(data == null)
{
data = CreateNewSettings(userName);
}
}
<br>
public string Name
{
get
{
return data.Name;
}
}
<br>
public string AccountType
{
get
{
return data.GetSetting("AccountType",DefaultSetting.AccountType);
}
set
{
data.StoreSetting("AccountType",value);
}
}
<br>
public string StartUpView
{
get
{
return data.GetSetting("StartUpView",DefaultSetting.StartUpView);
}
set
{
data.StoreSetting("StartUpView",value);
}
}
<br>
public Color UIColor
{
get
{
return data["UI"].GetColor("BackColor");
}
set
{
data["UI"].StoreColor("BackColor",App.ViewManager.UIColor);
}
}
<br>
public int TreeViewWidth
{
get
{
return data["UI"].GetSetting("TreeViewWidth",this.TreeViewWidth);
}
set
{
data["UI"].StoreSetting("TreeViewWidth",value);
}
}
<br>
public string DataFolder
{
get
{
return data["Folders"].GetSetting("Data",);
}
set
{
data["Folders"].StoreSetting("Data",value);
}
}
}
Okay, so here we have created a wrapper to strongly type the settingsFile. The important thing to note here is that this user's settings may or may have not exsisted, we are able to expand the settingsFile at runtime.
SettingsXpress, was designed to allow you to store simple data quickly without having to write alot of code.
I can think of anything and start storing the data right away no set-up, I don't even have to create the file ahead of time. For example, Addresses.
SettingsFile.Create("Addresses.dat")
<br>
SettingsKey steve = SettingsFile.Settings["Addresses/Steve"];
<br>
steve.StoreSetting("Street","123 Visual Studio road");
steve.StoreSetting("City", "CodeProject");
steve.StoreSetting("State","Shock");
steve.StroeSetting("Zip", "05347");
<br>
SettingsFile.Update()
Output would look something like this:
<Settings>
<Addresses>
<Steve Street="123 Visual Studio road" City="CodeProject" State="Shock" Zip="05347"/>
</Addresses>
</Settings>
Important Note: SettingsXpress uses the current users appData folder by default. Be sure to remove the '*' in your assemblies VersionAttribute whenever you use the appData windows folder. Otherwise a new folder for your applications data will be created everytime you compile your application. It is also a good idea to set your assemblies CompanyAttribute. For example: By setting the VersionAttribute for an application called SettingsXp Demo to '1.0.0.0', and setting the CompanyAttribute to 'Star Systems', then the default location of the settings file would be: C:\Documents and Settings\Amber\Application Data\Star Systems\SettingsXp Demo\1.0.0.0\Settings.Xml [Notice how windows uses the company and version attributes to group application data folders.]
SettingsXpress is still in it's infantcy. In the near future you will be able to store and load all properties of an object to and from the SettingsFile.
I would love to here more suggestions, and comments.
I hope that some of these examples have helped to clarify this article a bit.
Thank you
Amber Star
Visit My WebLog..
|
|
|
|
 |
|
 |
Could you tell me where this library is located? I can't seem to locate it.
|
|
|
|
 |
|
 |
nUnit is a testing framework, you can find it at www.nunit.org
|
|
|
|
 |
|
 |
The source code is now included in the download.
The solution file is Visual Studio 2003.
However you should be able to create your own project in 2002, using the .cs source file.
Amber
"If we can put a man on the moon, why can't we put all men on the moon?"
|
|
|
|
 |
|
 |
This is great, but in a world of back doors and other vulnerabilities, it is very difficult to include code in your project that you can't vet for malicious logic. This is a fantastic contribution, but basically useless without the source code.
Beyond that, I'd love to use it, but modify it to store the settings in a user-specific database entry to make it machine independent.
Give these concerns/desires, would you be willing to post the source code?
Thanks...Great implimentation of a much needed concept .
Chuck King
|
|
|
|
 |
|
 |
I thought that any contribution to CodeProject had to include source....
so where is it?
regards,
Darka
|
|
|
|
 |
|
|
 |