Shared settings

G

Guest

I have a solution with multiple projects, each with its own EXE, and its own
Properties.Settings.... They are all part of the same solution.

I want to have a set of settings that are shared by all of the EXEs. That
is, each project will have its own set of settings that are a superset of the
solution settings.

Under 1.X with appSettings, I could do this with by specifying a file=
attribute (KB article ID 555396) and the target was integrated into the
settings of all referencing projects.

Under 2.0, appSettings is replaced by applicationSettings and the file=
attribute is gone. http://www.devx.com/dotnet/Article/34273/1954?pf=true
discusses how to distribute settings in multiple files, but the resulting
files must be stored in the Properties folder of the project and therefore
can't be shared by multiple projects.

Can each project's settings be set up so as to derive from the solution
level settings?

I'm sure that there must be a way to handle this under 2.0, but I can't find
it.

Thx
Marc
 
K

Kevin Spencer

If you set Application Settings in a Project, and they are also set in the
executable Project of a Solution, the Application Settings in the executable
Project will be used, and written to the output appName.exe.config file. If
you set Application Settings in a Project that do not exist in the
executable Project of a Solution, they will be added to the executable
output appName.exe.config file.

So, it's actually easier to handle this with Visual Studio 2005. :)

--
HTH,

Kevin Spencer
Microsoft MVP

Printing Components, Email Components,
FTP Client Classes, Enhanced Data Controls, much more.
DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net
 
G

Guest

Sorry Kevin, still confused...

I have four projects that are logically executable, that is, I am creating
an exe for each and the user will run them individually. Say these were
called A, B, C, and D. When I package and deploy, in addition to the exe's, I
have A.exe.config, B.exe.config, C.exe.config, and D.exe.config. I can see
these in my installed directory.

So I don't understand what you mean by the "executable project." I'm
assuming that that isn't the "Startup Project" that is used to select who
starts with F5.

I have a fifth project (E) which (because I haven't prevented it) also
creates an exe, but really just holds base classes that are used by the other
four and since I don't include it explicitly in my package, I have no
E.exe.config in the directory created by my install.

In my case, A has settings A1, A2, A3, B has B1, C has C1, C2, and D has D1,
D2, D3. Somewhere, possibly E because it's handy, I want to add properties
P1, P2, and P3. These should be visible to each of A .. D in addition to
their own "private" properties when each of them run.

If this is the question you answered, I'm just being dense. Please try
saying it differently.

Thx
Marc
 
L

Linda Liu [MSFT]

Hi Marc,

In .NET 1.x, we could set the 'file' attribute of the appSettings element
of a config file to specify an external file that contains custom
application configuration settings.

In .NET 2.0, we can now include configuration settings in a separate file
for all configuration elements that support the configSource attribute.
However, when we use the configSource attribute, we must move the entire
section to the separate file because there is no merging of element
settings.

There is a one-time write to the exe.config file when using the
configSource attribute.

I will illuminate it with a sample.

1.Create a WinForm application.
2. Double-click the Settings.settings under the Properties folder in the
Solution Explorer.
3. Add a setting named 'Setting1' with the value of 'setting1' in the
Settings.setting. Save the changes.
4. Double-click the app.config file in the Solution Explorer and add a
section named "MyExternalSection" as follows:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings"
type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="TestProject.Properties.Settings"
type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<!--Add a custom section here-->
<section name="MyExternalSection"
type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</sectionGroup>
</configSections>

<userSettings>
<TestProject.Properties.Settings>
<setting name="Setting1" serializeAs="String">
<value>setting1</value>
</setting>
</TestProject.Properties.Settings>
<!--Set the configSource attribute for the custom section. Note that we
can't include any setting within this section-->
<MyExternalSection configSource ="commonSettings.config">
</MyExternalSection>
</userSettings>
</configuration>

5. Create a config file named 'commonSettings.config' which contains the
following content:

<?xml version="1.0" encoding="utf-8" ?>
<MyExternalSection>
<setting name="Setting2" serializeAs="String">
<value>Setting2</value>
</setting>
</MyExternalSection >

6. Add a Button on the form. In the Button's Click event handler, add the
following code to read configuration setting from the external file. You
should add a reference to System.configuration assembly to the project
first.

using System.Configuration;
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(ReadSetting("userSettings","MyExternalSection",
"Setting2"));
}

string ReadSetting(string sectionGroupName,string
sectionName,string settingName)
{
Configuration configuration =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Get sectionGroup
ConfigurationSectionGroup sectionGroup =
configuration.GetSectionGroup(sectionGroupName);

// Get section
ClientSettingsSection section =
(ClientSettingsSection)sectionGroup.Sections.Get(sectionName);
// Get setting
SettingElement setting = section.Settings.Get(settingName);
// Read setting value
return setting.Value.ValueXml.InnerText;
}

7. Build the project and run the application. Click the button on the form
and you should see a message box pops up showing the value of Setting2
stored in the commonSettings.config file.

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
K

Kevin Spencer

Hi Marc,

I'm not sure I understand you now!

Hi Marc,

I'm having trouble understanding you at this point! Let me give you an
example from my own experience, and see if that helps.

I have a Windows Forms Project that creates an executable. In the Solution
for this project, I have another project which is a Control library; it
contains classes, Controls, and some Forms. I did not set this to build as
an exe file, but I *suspect* that it would work the same either way (I
haven't tried compiling it as an exe). I also have several other class
libraries.

The Control Library has a Settings file, which I access through Project
Properties. It contains a number of "default" Application Settings used in
this assembly. It also has its' own Resources, as do a couple of other the
class libraries that don't have any Controls or Forms in them.

The Main Project also has a Settings file, which I access through Project
Properties. Some of these are the same as the Settings in the Control
library, for use in the Controls from the Control library that the Main
Project executable uses.

When the Solution is compiled, the Main Project creates an
appName.exe.config file, which has the Settings from this Project in it. The
Settings are the ones that the Main Project has in its Settings file, and
the Controls in the Control library use these when the app is running.

An application uses a single appName.exe.config. Any class being used by
that application will use the appName.exe.config file which the application
is using.

--
HTH,

Kevin Spencer
Microsoft MVP

Printing Components, Email Components,
FTP Client Classes, Enhanced Data Controls, much more.
DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net
 
G

Guest

Linda,

Thanks for the response. Your sample worked as advertized - One small glitch
is that I had to set the properties on commonSettigs.config so that
CopToOutputDirectory was Copy If Newer to force it into the bin\debug
directory.

Comments ...

#1
With regular settings I can say
double myDbl = Properties.Settings.Default.doubleSetting;
and it will do the conversion for me. The strategy you described loses this
functionality.

If the 1.x approach retained this (i.e., shared settings had the same
behaviour as private settings) then the 2.0 approach is a major step
backwards.

#2
I'm assuming that I could have done the same with Applications Settings as
opposed to User Settings, but I didn't test this.

#3
My problem is having multiple projects using their own settings plus an
additional set of shared settings. I think that this would still work and it
wouldn't matter which project I used to save the commonSettings.config file
so long as it went along with the distribution (msi).

#4
I don't understand what, if anything, any of this has to do with the
"exe.config" file.


Conclusion
While I understand that this approach provides partial integration with the
settings architecture (user settings, application settings, save and update),
these aren't applicable to my problem where I'm simply after some "constants"
that I want to be able to adjust.

I think that things will be much simpler if I just have an external file
with name value pairs and load these into a singleton collection at app load
time. I could easily add outbound serialization to this if I needed to.

Its unfortunate that MS couldn't have built a more fully integrated
approach. Sigh...

Thanks again for the help - it was a very enlightening exercise. I really
appreciate the effort you put into it.

Marc
 
L

Linda Liu [MSFT]

Hi Marc,

Thank you for your detailed feedback.
If the 1.x approach retained this (i.e., shared settings had the same
behaviour as private settings) then the 2.0 approach is a major step
backwards.

In .NET 1.x, the appSettings model is not strong typed. We could use
ConfigurationSettings class to read configuration sections as well as
common configuration settings.

However, in .NET 2.0, application settings model is strong typed. When you
use the statement ' double myDbl =
Properties.Settings.Default.doubleSetting;' to read an application setting,
you are using the strong typed class-Properties.Settings, which is
generated by VS automatically. One limitation of the above strong typed
class is that we could only read those settings which are contained in the
exe.config file using the automatically created setting class.

The method to read application settings in .NET 2.0 I provided in my first
reply is a general way, with which we could read any specified config file
as well as shared settings.
I'm assuming that I could have done the same with Applications Settings
as opposed to User Settings, but I didn't test this.

Yes, you're right. You could do the same with application scoped settings.
My problem is having multiple projects using their own settings plus an
additional set of shared settings. I think that this would still work and
it wouldn't matter which project I used to save the commonSettings.config
file so long as it went along with the distribution (msi).

No matter where you place the shared config file, you should ensure the
configSource attribute in the exe.config file has a correct path to the
shared config file.
I don't understand what, if anything, any of this has to do with the
"exe.config" file.
Could you please tell me what you mean in the above sentence?
Its unfortunate that MS couldn't have built a more fully integrated
approach.
As I have explained above, this is mainly because the application settings
model in .NET 2.0 is different from .NET 1.x.

Hope this helps.
If you have any concern, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support
 
G

Guest

Kevin,

Re: your comment...
The Control Library has a Settings file, which I access through Project
Properties. It contains a number of "default" Application Settings used in
this assembly. It also has its' own Resources, as do a couple of other the
class libraries that don't have any Controls or Forms in them.

The Main Project also has a Settings file, which I access through Project
Properties. Some of these are the same as the Settings in the Control
library, for use in the Controls from the Control library that the Main
Project executable uses.

When the Solution is compiled, the Main Project creates an
appName.exe.config file, which has the Settings from this Project in it. The
Settings are the ones that the Main Project has in its Settings file, and
the Controls in the Control library use these when the app is running.

From the above, I think that if you had a setting in the CONTROL LIBRARY
project called MYCONTROLSETTING, when you were using the VS code editor in
that project, you would get the expected autocomplete behaviour when you
typed "Properties.Settings.Default.MYC" ie., it would complete to
MYCONTROLSETTING.

However, if you then included that control in another (executable
generating) project, and in that project's settings you DID NOT make an entry
for MYCONTROLSETTING, the app would fail at runtime because there was no such
setting. That is to say, the settings known to the executable are exactly
those that are explicitly created in that project's settings files.

If true, this means that:

#1
When including controls from other projects that I must check for settings
and make copies of these in the "composite" project.

#2
There is no scoping of setting names. If I reuse controls from various
projects I am exposed to name conflicts.

#3
If I enhance the control and have to add a setting, I have to go back to all
the projects that use it and update the settings. Otherwise after I rebuild
those projects to use the new control, the apps will fail at runtime (#1)

#4
If I discover that I need to tweek a setting in the control, I have to
manually go back and update that setting manually in all of the projects that
use it.

Marc
 
G

Guest

Linda,

Thanks for your persistance. I think I understand exactly what you are
saying. Please see my reply to Kevin Spencer following in this thread. If my
comments are correct, then I do indeed understand the situation.

Thanks,
Marc
 
L

Linda Liu [MSFT]

Hi Marc,

I agree to most of your comments.
#2 There is no scoping of setting names. If I reuse controls from various
projects I am exposed to name conflicts.

Could you please tell me what you mean in the above sentence?

If we copy the settings in the Control Library to a WinForms application
project, these settings will have the namespace of the WinForms application
project.


Sincerely,
Linda Liu
Microsoft Online Community Support
 
G

Guest

Linda,

Much as I appreciate it, you are putting too much work into this for me -
but every time you reply, I get a hint about yet something else that I don't
understand.
projects I am exposed to name conflicts.

Could you please tell me what you mean in the above sentence?

If we copy the settings in the Control Library to a WinForms application
project, these settings will have the namespace of the WinForms application
project.

What I meant was this... Suppose that some time ago I built a custom control
in a project and it required a setting called CustomControlSetting (value:
"abcd"), and of course, when I created the control, I added this to the
settings page for the project.

Sometime later, on another project, I created another custom control that
also needed a setting and, not remembering the previous project, and because
the name made sense in context, I also called this setting
CustomControlSetting (value: 27.325).

Now, I'm working on another application and remember the previous work and
want to incorporate the two custom controls I designed earlier. I need to add
their settings to the new project's settings page, and Oops, I can't have two
settings, both named CustomControlSetting.

This example is a little contrived, but it isn't unreasonable if I was in
habit of building things so that they could be reused.

What I'm intrigued about are your comments ...
If we copy the settings ...
... these settings will have the namespace of the WinForms application

By "copy" do you mean anything other than manually typing the names and
values into the new project settings page? It would be neat if in the build
process you could "include" settings from other projects and have a syntax
like

namespace1. Properties.Settings.Default.MyCustomSetting
and namespace2.Properties.Settings.Default.MyCustomSetting

Thanks again,
Marc

Marc
 
L

Linda Liu [MSFT]

Hi Marc,

Thank you for your detailed explanation.

I do understand what you mean now. You're totally right that if the two
settings in the two custom control projects have the same name, there will
be a name conflict when you're trying to add the two settings into the new
project's settings page.

By "copy" I mean maually typing the names and values into the new project
settings page. Sorry that I didn't clarify in my last reply and caused the
confusion.
It would be neat if in the build process you could "include" settings
from other projects and have a syntax like

namespace1. Properties.Settings.Default.MyCustomSetting
and namespace2.Properties.Settings.Default.MyCustomSetting

I don't think it is possible in .NET 2.0.

As we have discussed, we could only use the configSource attribute to
specify an external config file (in this case, we need to use the
Configuration and ConfigurationManager classes to access the shared
settings) or manually add settings into the new project (at this time, we
could use the strong-typed class to access the settings, i.e.
Properties.Settings.Default.MyCustomSetting).

If you have anything unclear, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top