Search code examples
c#xmlwinformsconfigurationmanager

Loading user settings from XML with settings.Object not set to an instance of object


My WinForm program saves out an xml copy of user settings, the problem I'm having is loading it back in again.

I have copied this code from a blog: Code Snippet

The error occuring happens where commented in the code below.

Could not import settings. Object reference not set to an instance of an object.

[Update] I have just noticed that it actually works when running the program from Visual Studio 2013, however does not when run from Windows File Explorer.

[Update2] I think because it is the first time I had run this from the desktop, I'm a different user and my user settings config file has not been created yet, this is the issue.

try{
    var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);

    // returns "[MyApplication].Properties.Settings";
    string appSettingsXmlName = Properties.Settings.Default.Context["GroupName"].ToString();
    // Open settings file as XML
    var import = XDocument.Load(filename);
    // Get the whole XML inside the settings node
    var settings = import.XPathSelectElements("//" + appSettingsXmlName);

    //***Error occurs in the following code***
    config.GetSectionGroup("userSettings")
        .Sections[appSettingsXmlName]
        .SectionInformation
        .SetRawXml(settings.Single().ToString());

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

    appSettings.Reload();
}
catch (Exception ex)
{
    MessageBox.Show("Could not import settings. " + ex.Message);
}

Here is the XML file:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="DropLib.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
        </sectionGroup>
    </configSections>
    <userSettings>
        <DropLib.Properties.Settings>
            <setting name="ORG_SETTINGS" serializeAs="Xml">
                <value>
                    <ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                        <string>ORG1-||-server1-||-Proj 94-||-email@ORG1.com-|||-Server-|-Server-|-Folder$-|-http://server1/proj-|-c:\inetpub\wwwroot\proj\</string>
                        <string>ORG2-||-server2-||-Proj 94-||-email@ORG2.com-|||-Server-|-Server-|-Folder$-|-http://server2/proj-|-c:\inetpub\wwwroot\proj\</string>
                    </ArrayOfString>
                </value>
            </setting>
        </DropLib.Properties.Settings>
    </userSettings>
</configuration>

Solution

  • It seems that you are a different user depending if you run from VS or from the desktop.

    When I ran the program from the desktop for the first time, a user.config file had not been created yet.

    Solution: Added a check to see if the user.config had been created, if not perform a save of the user settings, which will create it.

    New Code:

    try
    {
        var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
        //Check user.config exists
        if (!File.Exists(config.FilePath))
        {
            [EDIT]
            DropLib.Properties.Settings.Default.MY_SETTING = "";
            [/EDIT]
            DropLib.Properties.Settings.Default.Save();
            config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
        }
    
        // returns "[MyApplication].Properties.Settings";
        string appSettingsXmlName = Properties.Settings.Default.Context["GroupName"].ToString();
    
        // Open settings file as XML
        var import = XDocument.Load(filename);
    
        // Get the whole XML inside the settings node
        var settings = import.XPathSelectElements("//" + appSettingsXmlName);
    
        config.GetSectionGroup("userSettings")
            .Sections[appSettingsXmlName]
            .SectionInformation
            .SetRawXml(settings.Single().ToString());
    
        config.Save(ConfigurationSaveMode.Modified);
        ConfigurationManager.RefreshSection("userSettings");
    
        appSettings.Reload();
    }
    catch (Exception ex)
    {
        MessageBox.Show("Could not import settings. " + ex.Message);
        appSettings.Reload(); // from last set saved, not defaults
    }