1

I'm working on a windows based project , in this project we used multiple settings files in order to set text of controls for example buttons.settings, lables.settings and .....

now I need to change the content of these settings files with other values at run time, for this reason we created same settings files with same column "Name" but different values, now I really have problem with changing content of these settings files.

I tried to change content of my tow settings file by loading and saving them as xmlDocument, but unfortunately my app.config doesnt change by new values. I also used ConfigurationManager.RefreshSection ...

plz help me thnx in advance

Shima.Y
  • 373
  • 4
  • 9
  • 18
  • are you using winforms ? one more question, do you want the changed settings to take effect while the application is running ? or after restarting application? – Kapoor Nov 10 '15 at 11:28
  • yes Im using winform ..... yes I want to change it at run time while user is loging into the app I'll check his hardware lock then by checking user's version type I decide which setting content(eg labels2.settings) to load in my main setting(labels.setting).I was able to change setting content by XML load and save mathod, but my app.config doesnt get changes – Shima.Y Nov 10 '15 at 13:40
  • I'm removing my answer, since I guess I misunderstood it to be a localisation issue. Anyway, can you tell me what is the scope of setting that you have defined in your *.settings file is it - user? or application ?. If its user scope, then for the settings to take effect, all you need to do is call `Settings1.Default.Reload();` after changing the user.config. (`Settings1` being the `ApplicationSettingsBase`, automatically created by Visual Studio on adding Settings1.Settings file), and this wont change app.config but the changed value will come into effect from user.config file – Kapoor Nov 12 '15 at 13:58
  • thanx for you help, I'm using user scope. I want to change setting file first and then I expect my app.config to take effect , but it doesn't change! I persist on changing setting file first, because I want to change all of values in setting file with values of another setting file, not just changing some of values! – Shima.Y Nov 17 '15 at 09:15
  • I understand your set up now. In principal, Its absolutely fine for app.config to not get influenced by user scope settings. This behavior shall enable every user can have his/her own settings. Incase, the user has not changed the settings, the default values from app.config are used. – Kapoor Nov 17 '15 at 19:30
  • I also understand that you have various setting templates that you change at run time and would like the settings to come into effect, the only thing I'm assuming right now is that there templates are already in the form of user.config file. I'll add an answer to explain - – Kapoor Nov 17 '15 at 19:33
  • I have added a working sample to support your approach. Please check, i have added it as an update to my answer. let me know if it serves yr purpose or if there are any issue. – Kapoor Nov 28 '15 at 14:18
  • I'm adding the latest implementation, without xml document as a new answer since the previous one is already very long. – Kapoor Dec 03 '15 at 18:20

3 Answers3

2

I'll start from describing my setup, just to be sure that we are on the same page.

Thats my setting file - Settings1.settings, with just one setting Test, & the default value being DefaultValue

enter image description here

At this point, the default value is also copied to app.config.

Now, I have a template whose settings which shall come into effect at run time, Its in the form of user.config. And this is how it looks like - enter image description here

here is the code from working experiment -

private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show(Settings1.Default.Test); // this shows "DefaultValue" in a message box

        // Now change the user.config file with our template file - 

        //1. I get the location of user config
       var fileForUser = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath;

        //2. now I'll Place my template file, where user.config should be present 
       
        // create directory if it doesnt exist
        if(Directory.Exists(Path.GetDirectoryName(fileForUser)) == false) 
           Directory.CreateDirectory(Path.GetDirectoryName(fileForUser)) ; 
       
        // I have kept my template at E:\template.config
        File.Copy(@"E:\template.config", fileForUser, true);
       MessageBox.Show(Settings1.Default.Test); // this still shows "DefaultValue" because the user.config is not reloaded

        //3. Read the new setting 
       Settings1.Default.Reload();
       MessageBox.Show(Settings1.Default.Test); // this shows "Default Value is changed to ABC" because the user.config is now reloaded

    }

The App.config remains as it is & incase I delete the user.config or call Settings1.Default.Reset() then its the App.config which provides the application with default values

Hope it helps. Do let me know if it served yr purpose or not.

Update 1 Supporting the already tried approach by author of the question

Here is the working code to support yr approach, which will bring the settings file's setting in applicaion -

regret my typo - Lables2.settings, Lables.settings instead of Labels2.settings & Labels.settings

        {
            // 1. Open the settings xml file present in the same location
            string settingName = "Lables2.SETTINGS";  // Setting file name
            XmlDocument docSetting = new XmlDocument();
            docSetting.Load(Application.StartupPath + Path.DirectorySeparatorChar + settingName);
            XmlNodeList labelSettings = docSetting.GetElementsByTagName("Settings")[0].ChildNodes;

            // 2. Open the config file 
            string configFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            XmlDocument appSettingDoc = new XmlDocument();
            appSettingDoc.Load(configFile);
            XmlNodeList appConfigLabelSettings = appSettingDoc.GetElementsByTagName("userSettings")[0].
                SelectNodes("WindowsFormsApplication2.Lables")[0].ChildNodes;
            //ProjectName.Setting file

            //3. update the config file 
            for (int i = 0; i < appConfigLabelSettings.Count; i++)
            {
                var v = appConfigLabelSettings.Item(i).ChildNodes[0];
                v.InnerText = labelSettings.Item(i).InnerText;
            }

            //4. save & load the settings 
            appSettingDoc.Save(configFile);
            Lables.Default.Reload();


            MessageBox.Show(Lables.Default.Code); // test pass... shows A2
        }

My project settings - enter image description here

Thats the executable folder, where enter image description here

And this is how the labels2.settings look like

enter image description here

Update 2 Approach without xml document

All the setup is same & this is much cleaner. Please try -

 {

        // 1. Open the settings xml file present in the same location
        string settingName = "Lables2.SETTINGS";  // Setting file name
        XmlDocument docSetting = new XmlDocument();
        docSetting.Load(Application.StartupPath + Path.DirectorySeparatorChar + settingName);
        XmlNodeList labelSettings = docSetting.GetElementsByTagName("Settings")[0].ChildNodes;


        Console.WriteLine("Code {0} Group{1} Name{2}", Lables.Default.Code, Lables.Default.Group, Lables.Default.Name); //prints Code A1 GroupB1 NameC1


        //2. look for all Lables2 settings in Label settings & update
         foreach (XmlNode item in labelSettings)
         {
             var nameItem = item.Attributes["Name"];
             Lables.Default.PropertyValues[nameItem.Value].PropertyValue = item.InnerText;                
         }

         Lables.Default.Save(); // save. this will save it to user.config not app.config but the setting will come in effect in application
         Lables.Default.Reload();

         Console.WriteLine("Code {0} Group{1} Name{2}", Lables.Default.Code, Lables.Default.Group, Lables.Default.Name); //prints Code A2 GroupB2 NameC2

    }
Community
  • 1
  • 1
Kapoor
  • 1,388
  • 11
  • 21
  • I'm so sorry if I cant explain my problem clearly! but my prob is that I don't have new config file , I have new values in .Settings file and I want to change setting files value with new settings file , and then I expect that app.config get changes automatically. – Shima.Y Nov 18 '15 at 10:27
  • @Shima.Y , I'm sorry its been about 10 days without a solution, so I think I would like to understand your set up clearly - – Kapoor Nov 20 '15 at 11:45
  • Is your setup like this - 1> You have a app.config with default settings. 2> And you have setting.settings **xml**, kept in the same location from where the application is running. 3> you want to replace this setting.settings xml and need the app.config to get the changes. Are these 3 points correct ? ---------- Can you please add a sample of your - app.config & setting.settings. Also can you please add the code of the xmlDocument experiment you did (that you have mentioned in the quesiton) ? I would like to have a look at it to undestand what you have already tried and what did not work. – Kapoor Nov 20 '15 at 11:45
  • yest 3 steps are correct , sure I will add a sample as soon as possible – Shima.Y Nov 20 '15 at 19:15
  • @Shima.Y, certainly . I'm very sorry but I just now took a notice that you have added samples which I requested. I'll work on this today. – Kapoor Nov 28 '15 at 10:19
  • @Shima.Y, I have added a working sample to support your approach. Please check & let me know if it serves yr purpose or if there are any issue. – Kapoor Nov 28 '15 at 14:16
  • Thanx for reply, I'll try it and tell u the result – Shima.Y Nov 28 '15 at 18:11
  • @Shima.Y, sure.... and I'll make sure to check this thread regularly. TBH, I advocate more automatic setup for the configurations, but 1st things 1st, lets fix the problem you are facing. – Kapoor Nov 28 '15 at 18:25
  • @Shima.Y, did u get a chance to try the new approach ? does it solve the problem ? – Kapoor Dec 03 '15 at 15:27
  • thnx alot for your reply but unfortunately it didnt solve my prob. And I think there is no way to change setting at runtime – Shima.Y Dec 03 '15 at 15:52
  • @Shima.Y, I regret to know that. May be its the problem mentioned here - http://stackoverflow.com/questions/2008800/changing-app-config-at-runtime that xml document does not save changes to in some .net versions. – Kapoor Dec 03 '15 at 18:05
  • @Shima.Y, I've added a new implementation which does not use xml document. Please try it, It works on my system. I'm hopeful it work at yr end too. Please let me know the result. – Kapoor Dec 03 '15 at 18:17
1
 XmlDocument doc = new XmlDocument();
        //doc.Load(@"C:\Users\***\Documents\Visual Studio 2008\Projects\ChangingLablesRuntime\ChangingLablesRuntime\_Labels2.settings");
        //doc.Save(@"C:\Users\SHYAZDI.IDEALSYSTEM\Documents\Visual Studio 2008\Projects\ChangingLablesRuntime\ChangingLablesRuntime\_Labels.settings");

        doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);

        var root = doc.GetElementsByTagName("userSettings")[0];
        doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);

        var Config = System.Configuration.ConfigurationManager.OpenExeConfiguration(@"path of app.config");
        var root = doc.GetElementsByTagName("userSettings")[0];
        doc.GetElementsByTagName("userSettings")[0].SelectSingleNode("Zeus._Labels").InnerText = doc.GetElementsByTagName("userSettings")[0].SelectSingleNode("ChangingLablesRuntime._Labels2").InnerText;


        //var newEml = root.SelectSingleNode("ChangingLablesRuntime._Labels2");
        //var oldEml = root.SelectSingleNode("Zeus._Labels");

        //oldEml.InnerText = newEml.InnerText;

        //oldEml.ParentNode.ReplaceChild(newEml, oldEml);

        doc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);

        Config.Save(ConfigurationSaveMode.Modified);
        ConfigurationManager.RefreshSection("userSettings");

here is my code , lables2 is same as lables1 with different values, after running this code nothing happened.

this is piece of lables1.settings , that I want to replace with lables2.settings: Lables1.settings this is piece of lables2.settings : Lables2.settings

and app.config related code : app.config

app.config

Shima.Y
  • 373
  • 4
  • 9
  • 18
  • I'm very sorry but I just now took a notice that you have added samples which I requested. After your today's comment on my answer. I'll work on this today. – Kapoor Nov 28 '15 at 10:25
  • I have added a working sample to support your approach. Please check, i have added it as an update to my answer. let me know if it serves yr purpose or if there are any issue. – Kapoor Nov 28 '15 at 14:18
1

Perhaps its the problem with xmlDocument as mentioned here Changing App.config at Runtime

Please keep the setup same as my last response of label.settings & label2.settings.

And try this implementation

{

        // 1. Open the settings xml file present in the same location
        string settingName = "Lables2.SETTINGS";  // Setting file name
        XmlDocument docSetting = new XmlDocument();
        docSetting.Load(Application.StartupPath + Path.DirectorySeparatorChar + settingName);
        XmlNodeList labelSettings = docSetting.GetElementsByTagName("Settings")[0].ChildNodes;


        Console.WriteLine("Code {0} Group{1} Name{2}", Lables.Default.Code, Lables.Default.Group, Lables.Default.Name); //prints Code A1 GroupB1 NameC1


        //2. look for all Lables2 settings in Label settings & update
         foreach (XmlNode item in labelSettings)
         {
             var nameItem = item.Attributes["Name"];
             Lables.Default.PropertyValues[nameItem.Value].PropertyValue = item.InnerText;                
         }

         Lables.Default.Save(); // save. this will save it to user.config not app.config but the setting will come in effect in application
         Lables.Default.Reload();

         Console.WriteLine("Code {0} Group{1} Name{2}", Lables.Default.Code, Lables.Default.Group, Lables.Default.Name); //prints Code A2 GroupB2 NameC2

    }

It works for me, & because its without xmldocument, I'm hopeful it'll work at yr end too. Do let me know the result.

Community
  • 1
  • 1
Kapoor
  • 1,388
  • 11
  • 21
  • thanx a lot Kapoor, it worked for me and Im so happy , thank you sooooo much – Shima.Y Dec 05 '15 at 08:20
  • @Shima.Y, oh wow!! thats a great update! Trust me, I'm equally glad to know that it solved the problem at yr end :) – Kapoor Dec 05 '15 at 10:16
  • @Shima.Y, incase this config setup gives u any hard times in future (I sincerely hope, it doesn't, but just incase), please write me a comment. – Kapoor Dec 05 '15 at 10:19