Client Settings FAQ posted
We have been getting lots of feedback on the new Whidbey Settings feature that I have blogged about in the past. Since there are a set of questions many people ask as they begin to delve into the API, I thought it might be useful to post an FAQ that I can point folks to that should answer most of these questions. I posted this as an article instead of a regular blog post so I can update it off and on in the future.
If you have any suggestions for questions to add to the FAQ, please feel free to leave a comment here.
Comments
Anonymous
July 28, 2005
Hi Prabhu,
I had seen your "client settings" blog from part1 to part3, in all of these you are explaining about the ApplicationSettingsBase but I want to write my own custom SettingsProvider class. please help me out in
How to write a custom SettingsProvider class?I am asking this question as we could not able to get any links explaining it in better way. If you can provide any samples that will be helpful and also please provide us a solution how to set this custom SettingsProvider to the application, so that application reads the settings from the custom SettingsProvider rather than default LocalFileSettingsProvider
Thanks
MDeevi.Anonymous
July 29, 2005
There are a couple of sample SettingsProvider implementations in the Beta 2 SDK samples. These should get you started. Let me know if you could not find them.Anonymous
July 30, 2005
Sorry! Prabhu, I could not able to find the samples in Beta2 SDK. Can u please get me the links or sample code so that i will try to change according to our requirement.
Thanks
MDeevi.Anonymous
August 01, 2005
They are located in the .Net SDK documentation under .Net Framework SDK / Samples and QuickStarts / Samples / Technology Samples / Windows Forms Controls Samples.
Binding to Client Settings Sample
Demonstrates how to bind to application settings to reflect user changes.
Client Settings Web Service Client Sample
Shows how to use a Web service client to change application settings.
RegistrySettingsProvider Sample
Demonstrates how to persist application settings in the registry.Anonymous
August 01, 2005
Thanks Prabhu, Got the path for samples and could able to write custom SettingsProvider class. But there is a problem we are getting an error saying that
"Failed to load provider type: MyCustomSettingsProvider"
I configured my settingsprovider in the following way in Settings.CS file as
[SettingsProvider("MyCustomSettingsProvider", "MyCustomSettingsProvider")]
class Settings : ApplicationSettingsBase
{
. . . . . .
. . . . . .
}
Please try to help me out how to get rid of this error.
Thanks
MDeevi.Anonymous
August 01, 2005
You need to provide an assembly qualified type name to the attribute, something like:
[SettingsProvider("MyCustomSettingsProvider, MyAssembly, Version=1.0.0.0...")]
(replace ... with full assembly information)
Alternately, it is easier to use the other overload that takes a type:
[SettingsProvider(typeof(MyCustomSettingsProvider)]Anonymous
August 01, 2005
Thanks Prabhu for your quick response. Its working fine when I changed that to
[SettingsProvider("MyCustomSettingsProvider.CustomSettingsProvider", "MyCustomSettingsProvider")]
and also working if I had given it as
[SettingsProvider(typeof(CustomSettingsProvider))]
Thanks for your help. Now I want to use SQL Server 2005 Express to store my settings using the custom SettingsProvider. Can you give me some suggestions how to do that...
Thanks
MDeevi.Anonymous
August 04, 2005
Here's a scenario I can't figure out how to address. I have a service that is currently using the new .NET 2.0 settings. These settings have application scope. What I want to be able to do is to change them during the installation phase of the service. I'm not having any luck figuring out how to go about doing this though. Can a service even call Save() on the settings? Where would that persist to?
I can set the value of an application scoped setting by doing:
Properties.Settings.Default["SettingName"] = "Blah"
Upon calling Properties.Settings.Default.Save() though, the value disappears. Any suggestions?Anonymous
August 09, 2005
Application scoped settings are read-only and cannot be saved at runtime. See the FAQ linked above for more details.Anonymous
August 09, 2005
Can the path returned by Application.LocalUserAppDataPath and the path used by LocalFileSettingsProvider be the same? I need to store additional files, and it would make supporting the application alot easier if they could reside in the same directory (<AppPath>My Company<exe> versus <AppPath>My_Company<exe>_<signatures>).Anonymous
August 10, 2005
Blair: Unfortunately not. As I have explained in the FAQ linked above, the user.config file path needs to meet certain isolation and robustness requirements that are not met by Application.LocalUserAppDataPath. The latter cannot be changed due to compatibility reasons.
However, if your app is Clickonce deployed, both will be redirected to the Clickonce data directory and the only difference will be that the config file path will have a version dir.Anonymous
August 11, 2005
Could there be a way to get the path that the LocalFileSettingsProvider uses? For example, Properties.Settings.ApplicationPath and Properties.Settings.UserPath?
It really doesn't matter to me what the directory is. It just would be nice to put everything in same place.Anonymous
August 11, 2005
Here is how you can get the config file path.
First get the Configuration object for the desired level:
Configuration c = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
Now you can access the FilePath property off the Configuration object.
Note that you need to add a reference to System.Configuration.dll.Anonymous
August 12, 2005
Hey, that's great! You should put that into your FAQ.Anonymous
August 13, 2005
Good idea - added it to the FAQ.Anonymous
August 15, 2005
I created a custom Settings Provider and now I do not want to use the app.config file for the settings. Does it arises any issues if I am not going to use app.config file? Does app.config take priority over the settings class for assigning defaults?
Is there any mechanism in Visual Studio 2005 that we can tell the settings designer to generate the class but not the app.config values?
Please let me know about these details....Anonymous
August 16, 2005
If you aren't using the default provider, then the app.config file plays no part and is not required.
I don't know a way to tell the settings designer to not put values in it. However, you could probably just get rid of the app.config before deploying the app.Anonymous
August 16, 2005
The comment has been removedAnonymous
August 17, 2005
The user config files are per app domain, so it doesn't matter which assembly accesses them, provided it is in the same app domain. So as long as the settings classes have unique full names, you don't have to worry about it.
Another approach you might find useful here is IPersistComponentSettings. See the docs for more information about this. You will find some info in the comments section of the FAQ as well.Anonymous
August 18, 2005
How do we access the GroupName information from GetPropertyValues and SetPropertyValues in the custom SettingsProvider?Anonymous
August 18, 2005
You can access it off the SettingsContext: context["GroupName"].Anonymous
August 21, 2005
Hi Prabhu,
We have implemented a simple SqlCustomSettingsProvider based on the Registry example provided in MSDN Samples.
We have many settings and want to group them. In fact, we want to group them hierarchically, but that is outside the scope of the group name issue.
We noticed that using multiple settings classes is a logical way to group settings. However, we would like to use a single settings provider for all settings classes. The settings architecture documentation (ApplicationSettingsBase class) states that "each class defines a settings group" and that "if the group name is not explicitly set by decorating the wrapper class with a SettingsGroupNameAttribute, then a name is automatically generated".
Our design requires us to store the groupname in the settings database. This allows 2 different settings groups to each have a setting with the same name.
How do we access the GroupName information from GetPropertyValues and SetPropertyValues in the custom SettingsProvider?
Please kindly provide us some solution so that we can continue the rest of the things.....Anonymous
August 21, 2005
My comment above has the answer (repeating here):
You can access it off the SettingsContext: context["GroupName"].Anonymous
August 21, 2005
Thanks Prabhu, We will look into the solution provided by you. If we face any problem we will get back to you.
Thanks in advance....Anonymous
October 05, 2005
I have a big issue with client settings I would appreciate if you could comment on. When using strong names, the expected behavior of ApplicationSettingsBase.Upgrade() is thrown out the window if your version changes because an entirely new directory is created one level above the directory where side-by-side versions are contained, which apparently is the only place the default implementation of Upgrade() looks... Was this considered during the design and is it intentional? What is the recommended work-around? I am considering writing my own provider, because my assembly must be strong-named and I absolutely require upgrading settings with each release.Anonymous
October 06, 2005
TheMask: Yes, this was a bug in Beta 2 and has been fixed recently. You should see the fix in the RC and final releases of .NET 2.0.Anonymous
October 06, 2005
Unless I'm missin' something, it didn't make it into RC1, did it? I recently tested it and the problem was still there unfortunately. Guess I have to wait until release...
By the way, thanks for the quick response!Anonymous
October 06, 2005
You are right - I just checked and found that the fix missed the RC release by 3 days. Sorry for the confusion.Anonymous
October 17, 2005
I would like to have settings which are scoped which can be written by one user and and read by all users.
The UserScopedSettingsGroup doesn't work because the same user.config isn't read equally by all users. The ApplicationScopedSettingsGroup doesn't work because it is read only.
I realize I can create my own SettingsProvider but then I seem to lose the .config file location, grouping, heirarchy, and general structure provided by the LocalFileSettingsProvide.
Do you have any recommendations?
j
P.S. I also can't find the samples you mention in the faq on the Visual Studio RC1.
i.e. / .Net Framework SDK / Samples and QuickStarts / Samples / Technology Samples / Windows Forms Controls SamplesAnonymous
October 17, 2005
John: This scenario is not supported by the built in provider, so unfortunately, I would have to recommend building your own. However, this is a fairly simple task once you figure out where and how you want to store the settings. Stuff like serialization is taken care of for you by the settings API.
Here is the online link to the SettingsProvider samples:
http://msdn2.microsoft.com/en-us/library/ya940ct3(en-us,VS.80).aspx
Check out 'Client Settings Web Services Sample' and 'RegistrySettingsProvider Sample'.Anonymous
December 05, 2005
We have an application that dynamically loads DLLs using reflection. This is essentially a plug-in architecture - it looks for DLLs in a particular directory that implement a particular interface and loads them.
The question is this: Some DLLs need to have their own configuration data. With Visual Studio 2005, we're allowed to create the settings information for the DLL project, and all of the constituent files are created (app.config, settings.*). However, when the DLLs try to access data using Properties.Settings.Default, the settings are not loaded from dllname.dll.config. How can we cause each DLL's .config file to be loaded (and the Settings.Designer.cs properties to be loaded as a result)?Anonymous
December 05, 2005
Config files are supported only for applications (exe), not libraries (dll). As such, dlls need to store their config in the host app's config files. This should happen automatically for you - any settings you write at runtime will get written to the host application's config files. As for default settings, you can either put them in the exe.config of your application, or simply supply them in code by specifying a DefaultSettingValueAttribute (which VS 2005 will do by default).Anonymous
February 19, 2006
Hi;
We have a case where the dll is a Word Add-In and for securtiy reasons some of our customers will not allow any changes to winword.exe.config. They also will not allow any files to be placed in the Office subdirectories.
So we need to place config information with our dll (which is in a different directory). How can we set things so our dll can read from autotag.dll.config?
Again, this is a security limitation from some of our customers, we cannot use winword.exe.config.
thanks - daveAnonymous
February 20, 2006
The configuration system does not support config files for dlls, only exes. So to do something like this, you will need to implement a custom SettingsProvider. You can find samples/doc on how to do this on MSDN - it should be fairly easy.Anonymous
February 21, 2006
I know that ConfigurationManager.GetSection uses the cached instance of objects inside the ConfigurationManager. I have two questions:
1. Do the following two ways to access settings:
string str = Settings.Default.testSetting;
and
Settings set = Settings.Default;
string str = set.testSetting;
also use cached instances and what's the difference between them?
2. If I call a class that is inside my configuration class library that calls ConfigurationManager and returns ConfigurationSection instance to my application will there be caching for subsequent class calls in my application?Anonymous
February 21, 2006
Hi blog
I am trying to make an extension to my.settings as I want to save the application password encrypted.
I am trying to acomplish this by making a partial class:
Namespace My
Partial Friend NotInheritable Class MySettings
Inherits Global.System.Configuration.ApplicationSettingsBase
Private Function EncryptString(ByVal strPlain As String) As String
...
End Function
Private Function DecryptString(ByVal strCrypt As String) As String
...
End Function
<Global.System.Configuration.UserScopedSettingAttribute(), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Configuration.DefaultSettingValueAttribute("")> _
Public Property frmLoginPassword() As String
Get
Return Me.DecryptString(CType(Me("frmLoginPassword"), String))
End Get
Set(ByVal value As String)
Me("frmLoginPassword") = Me.EncryptString(value)
End Set
End Property
End Class
End Namespace
This seems to be working, but every time I modify the Project Application Settings, the frmLoginPassword property is re-created in the original class hence giving a:
'Public Property frmLoginPassword() As String' has multiple definitions with identical signatures.
Am I misusing the whole settings concept or is there a workaround?
RegardsAnonymous
February 22, 2006
TheXRay:
1. Yes, they use cached values (both are equivalent). If you wish to force a refresh, you can call Reload().
2. The config system does cache values, but you can call ConfigurationManager.RefreshSection() to force a read from the config file.
Muleskinner:
Yes, modifying designer generated code is not recommended, since it can get overwritten. Instead, you can either wrap this property in your own one or do the encryption/decryption by subscribing to one of the events in ApplicationSettingsBase.
This is an unfortunate limitation of dealing with designer generated code!Anonymous
February 26, 2006
> The configuration system does not support config files for dlls, only exes.
Will they address this in the future. I think security restrictions will make this more common - especially for Add-Ins.
thanks - daveAnonymous
February 26, 2006
David: I don't know the answer to that, since I work in a different group now. You could request it through MSDN Product Feedback or maybe contact Brad Abrams through his blog (http://blogs.msdn.com/brada/), since I think his team owns this now.Anonymous
March 01, 2006
I must admit even after reading the above, I'm still having trouble getting our data layer dll to use the main exe's configuration file for a connection string.
The exe has a config file and an application setting for connection strings.
The dll has an application setting for connections strings. I have tried labelling this the same and different from the the main executable.
I then alter the config file (the executables) in the test environment, and the application continues to fall over. It is easily fixed by hardcoding a valid connection string in the dll's settings, but this isn't configurable.
Help.Anonymous
March 02, 2006
The name of a setting in the config file will be a concatination of the full class name and property name, something like MyApp.MySettings.ConnStringSetting. Since the namespace and class name of the dll's settings class are different from that of the main exe, you might be seeing a mismatch.
Try using the SettingsGroupNameAttribute - it is designed to help in such scenarios. Look it up in MSDN for more info.Anonymous
April 28, 2006
The comment has been removedAnonymous
April 29, 2006
I recommend using fuslogvw (a tool that ships with the .NET SDK) to track down assembly load problems. Just start it up and set it to catch assembly load issues. Then run through your scenario. You should see an entry in fuslogvw corresponding to your load failure - it should have details on why the load failed.Anonymous
May 02, 2006
Sorry for the delay -- I was busy on another project briefly, and then this took a while to figure out. The problem seems to be: while "normal" assemblies referenced by the COM object are loaded in the LoadFrom context, the SettingsProvider was loading (or failing to load) in the Default context. The upshot of this was (as I suspected) it was probing the calling App's directory, not the COM object's. The Fusion Log viewer helped confirm that -- it's a good tool that I was unaware of. Thanks very much for the pointer.
The fix was to load the assembly in the AppDomain's AssemblyResolve event.:
[VB] Return GetType(DBSettingsProvider).Assembly
or
[C#] Return typeof(DBSettingsProvider).Assembly
Why, (you may ask) did my experiment of just moving the provider assembly to the calling app's directory not work? I had an unrelated bug: When initializing the provider, I was accessing Assembly.GetEntryAssembly().GetName().Name, but in the COM object, GetEntryAssembly() is Null/Nothing.
So, thanks for the tip -- I could have gone around in circles for a long time looking at that.Anonymous
May 02, 2006
No problem - glad to know you were able to resolve the issue!Anonymous
May 03, 2006
Thanks again for the help. While I'm picking your brain...
I can't seem to find any way to set values in the Config parameter that gets passed to the SettingsProvider's Initialize method. Are there attributes I'm missing, or some other method of adding Name/Value pairs to Config?Anonymous
May 08, 2006
The config parameter is of type NameValueCollection (http://msdn2.microsoft.com/en-us/library/system.collections.specialized.namevaluecollection.aspx)
You should just be able to use the Add method?Anonymous
May 08, 2006
Yes, I'm familiar with the NameValueCollection type.
The problem is that the Initialize method is called from somewhere within the CLR, so I don't have direct access to the collection. I can't figure out how to let the CLR know what I want to put in that NameValueCollection parameter when it calls Initialize on my SettingsProvider.Anonymous
May 08, 2006
Ah, okay. Let me preface this reply by saying that its been ~6 months since I moved to a different team in Microsoft, so I am not as familiar with this stuff as I was before.
IIRC, in the client app case (i.e., when your provider is used through ApplicationSettingsBase), the parameters to Initialize will both be always null, and don't mean anything.
In the ASP.NET case, I think each provider is associated with a section in config that declares the provider. The config parameter passed to Initialize contains the values specified in this section.
Make sense?Anonymous
May 10, 2006
Got it. So in the Windows Forms case, I'll need to get my initialization information from other (persistent) sources. The application/consumer of the settings can't pass me anything.
That's not great news, but better to know than to wonder. Thanks for the Info.Anonymous
August 29, 2006
I know you've stated before if you want to change where the user.config file is saved you have to write your own settings provider, but I like everything about LocalFileSettingsProvider except the "Evidence" stuff that it appends to the application name in the path to user.config. Is there anyway to extend LocalFileSettingsProvider and just override this on piece?Anonymous
August 30, 2006
Doug: Unfortunately, no, there isn't a way to override the user.config path through the LocalFileSettingsProvider, since the path is constructed by the config system when the app domain loads. The LFSP doesn't itself control the path construction.
Just curious though: why do you wish to override the Evidence part of the path?Anonymous
August 31, 2006
The comment has been removedAnonymous
September 05, 2006
The Evidence portion is appended to your path to prevent collision with other applications that might happen to have the same name (unlikely that both company name and app name will match, but not impossible - also, a security risk). Specifically, the isolation is provided at the app domain level.
The evidence is pulled from the 'Evidence' object associated with the app domain. If your app is signed, then the evidence depends only on the key you use - if the signature changes, so will the evidence, otherwise no. If not signed, then the evidence is based on the path to your application.
So basically, changing the assemblies loaded do not affect the evidence portion of your user.config path.Anonymous
September 05, 2006
The comment has been removedAnonymous
September 05, 2006
Yes, IIRC, that's correct. Please confirm experimentally though, since, as I have mentioned before, it's been nearly a year since I worked on this stuff, so don't take my word for it!Anonymous
September 07, 2006
The comment has been removedAnonymous
September 07, 2006
Hmm, that should work. Try a simple example with a fresh small application in VS 2005 and see if it works for you.
Also, try running without the VS 2005 debugger attached - the debugger's hosting process can cause the signature evidence not to be picked up by the config system. If this is the case, you can disable the hosting process (it is one of the debugger options).Anonymous
September 08, 2006
The comment has been removedAnonymous
September 08, 2006
Ah yes, the app should be strong named - it is the strong name evidence that will be used to isolate your app's user.config path. AFAIK, you cannot get this to work without strong naming.
What's your concern with strong naming?Anonymous
September 12, 2006
The comment has been removedAnonymous
October 04, 2006
Hi, I'm back. I'm trying to write a custom SettingsProvider and from looking at the examples (which aren't very complete by the way since they don't implement IApplicationSettingsProvider) when getting a value from storage, they are only setting the SettingsPropertyValue's SerializedValue and not the PropertyValue. When I do this, the SerializedValue is correct but the property is always returning the default value. Could you explain the interactions between the PropertyValue and SerializedValue and how they are used to determine the value of the property?Thanks.Anonymous
October 09, 2006
IIRC, if you set the SerializedValue and query the PropertyValue, it will automatically deserialize it. If there is an error while deserializing, it will return the default value automatically. If you want to change this behavior to instead return exceptions when the deserialization fails, you could set the ThrowOnErrorDeserializing property on the SettingsProperty object to true.Anonymous
November 14, 2006
Hello, I'm late to this chat (which has been really helpful) so I hope you're still there... I've created a custom ServiceProvider that reads/writes settings to a specific location used by a DLL. This is working a charm when the DLL is initialised by a .Net application thread. The problem is that the DLL is also loaded in a COM thread. In this case, the attribute [SettingsProvider(typeof(Csaaw.CsaawLogic.CsaawSettingsProvider))] is seemingly ignored (the SettingsProvider's constructor is not called). Also, if I interogate the Providers property of my Settings class (to get its Count) I receive the following exception: Failed to load provider type: Csaaw.CsaawLogic.CsaawSettingsProvider, CsaawLogic, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null. I've been unable to figure out why my custom ServiceProvider would behave differently under COM whereas the LocalFileServiceProvider works fine. Any thoughts?Anonymous
November 15, 2006
I've resolved the issue. In case anyone else encounters a similar problem, the resolution was to install my DLL in the Global Assembly Cache (GAC). The problem was that when my COM application was using the DLL, the Deserialize(...) method would be looking for the DLL in the COM application's Path. Adding my DLL to the GAC made it visible to the Deserialize(...) method.Anonymous
November 15, 2006
Rob: I was just composing a reply to your comment, when I saw that you resolved the problem. Cool :-) Note that in general you can use the tool called fuslogvw (available in the SDK) to debug assembly/type load failures of this kind.Anonymous
November 15, 2006
Thanks for the tip and for hosting the discussion. Without it I would've been pretty stuck! RobAnonymous
June 18, 2009
PingBack from http://outdoordecoration.info/story.php?id=1525