51

Is there a way to access the settings file from a different project? For example, I have a solution that contains 2 projects (Lets call them Proj1 and Proj2). I want to access the application settings of Proj2 from Program.cs in Proj1. Is this possible?

KrisTrip
  • 4,943
  • 12
  • 55
  • 74

8 Answers8

61

The answer if you are using C#:
The very simple answer is to right click on proj2, choose the settings tab. On the top, you will find the access modifier of the settings class is: internal, change it to public. Add a reference to the proj2 in the proj1 in order to see the proj2 Settings class. That's all.

Naser Asadi
  • 1,153
  • 18
  • 35
Nour El-Dien
  • 629
  • 5
  • 2
  • 7
    Ok, this definitely makes sense, but how are you supposed to change these settings without compilation? Lets say you deploy project A, with referenced settings of project B. You want to modify settings from project B, but all you have is default values compiled into the dll? As thats the only explanation i can find, since there is no config file deployed or merged with settings of project A. – mikus Nov 22 '13 at 15:38
  • I tried this and it works, but it has the limitation stated by @mikus. Also, if you are using XML transforms (e.g. with SlowCheetah) the changes from the transforms will not be seen by Proj1, even with a recompile. – Matt Miller Apr 09 '14 at 18:41
  • 2
    If I could up-vote this twice I would have, seeing as how I googled this question and found this post... that I apparently have already up-voted. – Tony Nov 03 '15 at 18:30
  • @Patrick don't forget to build `proj2` after changing the modifier of the class to `public`. – Daniel Bonetti Aug 08 '16 at 14:23
  • 1
    Thanks! This might not be oblivious to all but you also need to reference the other projects settings as "other project name".Properties.Settings.Default."property name" – Kevin Moore Aug 29 '18 at 19:39
  • Also, if your Proj2 is already referencing the Proj1, you will run into circular dependencies problem. – nPcomp Jan 02 '19 at 00:23
  • VB.NET users, this doesn't work for us. Viewing _MySettings_ in Object Viewer shows that the class is marked Public, but you can't seem to get to it. (All projects have the same name/namespace in the same solution, eg _MyNamespace.My.MySettings_.) It's pretty frustrating as all I want to do is read an application setting from a sub-assembly project that's referenced in my main project. Why should that be so difficult? – SteveCinq Feb 25 '19 at 03:48
42

Option A : parse the values out of the other assembly's configuration file (where the settings are stored)

Option B : create a public class in Proj2 that exposes the necessary values from its settings as static properties, then reference the assembly in Proj1 and consume the values from that class.

Option C : If you want to expose ALL the settings, you can modify the access of the settings class from internal to public.

I'm sure there other ways as well.

Jay
  • 56,361
  • 10
  • 99
  • 123
5

I'll repost the contents of @Kildareflare's link for future reference. Still works in VS2015, but for myself I think I prefer "Option B" above.

Getting access to Settings in another project

One of the new cool features of Visual Studio 2005 is the new property editor. With this property editor you can easily add setting to your application. But there is a problem the way it's implemented. Let me explain you why.

Usually the settings are specific to a project. When you add a setting in a project a special custom tool associate with the setting file generates a new class which you can use to access it. What is good about this class is it’s strong typed. But behind the scene it’s just getting a key from an xml file. This generated class is set as "internal sealed". This prevent from being accessed from any other assembly. What if you want to centralize where you edit these settings.

After many attempt to expose it I found a quick an easy way to do it. Let’s say we have 2 project in our solution: an Engine and a WinApp. Each have settings but we want them to be editable from WinApp. Here is what it look like.

Settings Before

If you want to get access to Engine settings here the trick: Add a link file.

Add Link

The link file will be compiled as part as you WinApp project. The setting class will still be internal and sealed but to WinApp project instead of Engine.

Here is the final result:

Settings After

Notice that I added a folder with the same name as my Engine project. This will be helpful if you want to add settings from many projects.

With this in place you can access you engine setting the way from you engine class as from your WinApp class. You may omit the “Engine” part from your engine class because you should be in the same namespace. Here is what it should look like:

namespace WinApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public void AccessConfig()
        {
            Engine.Properties.Settings.Default.EngineSetting = "test";
        }
    }
}
woodvi
  • 1,898
  • 21
  • 27
  • This doesn't work for me. I'm still getting `'Settings' is inaccessible due to its protection level` – Mugen Oct 31 '17 at 09:07
1

ConfigurationManager has that covered:

string proj2Exe = @"C:\projects\proj2\bin\Debug\proj2.exe";
Configuration proj2Config = ConfigurationManager.OpenExeConfiguration(proj2Exe);
string mysetting = proj2Config .AppSettings.Settings["ThatSetting"].Value;
James Cooke
  • 1,086
  • 8
  • 7
0

I had to come up with another solution besides the ones already given here because I was using XML Tranforms (via SlowCheetah) on the App.config of my project containing the settings. If you are not doing this, I recommend one of the other solutions.

I added an after-build step in the consuming project (Proj1 in the example) to copy the config file from the output folder of Proj2. This will ensure that the config will have the transforms applied. (In my case, Proj1 is a dll, so if yours is an exe, change the DestinationFiles from ".dll.config" to ".exe.config".) Snippet from Proj1.csproj:

<Target Name="AfterBuild">
  <Copy SourceFiles="..\Proj2\bin\$(Configuration)\Proj2.exe.config" DestinationFiles="$(TargetDir)\$(AssemblyName).dll.config" />
</Target>

Then I created a link of the Settings.settings from Proj2 by ctrl+shift+dragging the file to Proj1 (as in the blog article referenced by Kildareflare).

I could then reference settings in Proj1 similar to: Proj2.Properties.Settings.Default.MySetting.

Note: If you are doing this for unit tests like I am (Proj1 is a test DLL), and you are using the ReSharper test runner, be sure to configure it to run tests in separate AppDomains.

Community
  • 1
  • 1
Matt Miller
  • 443
  • 4
  • 10
0

I've not tested this method myself but Eric De Carufel's little trick may be what you need:

http://blog.decarufel.net/2007/10/getting-access-to-settings-in-another.html

The original link appears to be dead as he has moved to a new blog and deleted old content.

The original content is below:

Getting access to Settings in another project

Thursday, October 25, 2007

One of the new cool features of Visual Studio 2005 is the new property editor. With this property editor you can easily add setting to your application. But ther is a problem the way its impelemented. Let me explain you why.

Usually the settings are specific to a project. When you add a setting in a project a special custom tool associate with the setting file generates a new class which you can use to access it. What is good about this class is it's strong typed. But behind the scene it's just getting a key from an xml file. This generated class is set as "internal sealed". This prevent from beeing accessed from any other assembly. What if you want to centralize where you edit these settings.

After many attempt to expose it I found a quick an easy way to do it. Let's say we have 2 project in our solution: an Engine and a WinApp. Each have settings but we want them to be editable from WinApp. Here is what it look like.

If you want to get access to Engine settings here th trick: Add a link file.

The link file will be compiled as part as you WinApp project. The setting class will still be internal and sealed but to WinApp project instead of Engine.

Here is the final result:

Notice that I addes a foler with the same name as my Engine project. This will be helpfull if you want to add settings from many projects.

With this in place you can access you engine setting the way from you engine class as from your WinApp class. You may omit the “Engine” part from your engine class because you should be in the same namespace. Here is what it should look like:

namespace WinApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public void AccessConfig()
        {
            Engine.Properties.Settings.Default.EngineSetting = "test";
        }
    }
}
Polluks
  • 525
  • 2
  • 8
  • 19
Kildareflare
  • 4,590
  • 5
  • 51
  • 65
0

Faced with this trouble today, mate. Solved by adding the settings section of the second project between configSections of the first project's app.config file

<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxx">
      <section name="fullSecondProjectName" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxx" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>

and then don't forget to add those user settings

<configuration>

  <configSections>
    <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxx">
      <section name="fullSecondProjectName" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxx" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
    </sectionGroup>
  </configSections>

  ...

  <userSettings>
    <fullSecondProjectName>
      <setting name="LogMethodInvocation" serializeAs="String">
        <value>True</value>
      </setting>
    </fullSecondProjectName>
  </userSettings>

</configuration>
ikhtiyarnovruzov
  • 131
  • 3
  • 10
-1

Since Settings.Designer.cs is an internal class, and you don't want to mess with a generated code file, I would recommend to add the secondary as a "friend" project.

From: C# "internal" access modifier when doing unit testing

Add following code to the Proj2's AssemblyInfo.cs

using System.Runtime.CompilerServices;

[assembly:InternalsVisibleTo("Proj1")]
Mugen
  • 8,301
  • 10
  • 62
  • 140