0

Today I thought, Oh, I'll just add some SQL logging to a C# SFTP custom (console) program we have. I didn't write it, and it has perhaps an odd configuration file. It looks like the SQL Performance Counters require a well conformed config file? Add the catch for TypeInitializationException gave some more specific and useful info.

So I am getting the connection string from the app.config file, but to show why I'm frustrated, I hard-coded the connection string below. If I'm providing a full connection string, why would it go to the config file. Apparently SqlPerformanceCounters is picky about these things???

            if (!String.IsNullOrWhiteSpace(SqlConnectionString))
            {
                try
                {
                    WriteLogConsole("SqlConnectionObj - about to open with SqlConnectionString='" + 
                                     SqlConnectionString + "'");

                    //SqlConnection SqlConnectionObj = new SqlConnection(SqlConnectionString); 
                    // Even using a hard-coded connection string I have this issue! 
                    SqlConnection SqlConnectionObj = new SqlConnection("Server=abc;Database=MyDBName;Trusted_Connection=true"); 
                    SqlConnectionObj.Open(); 
                    WriteLogConsole("SqlConnectionObj - opened successfully");
                }
                catch (TypeInitializationException ex)
                {
                    WriteLogConsole("TypeInitializationException=" + ex.ToString());
                    // don't stop, keep going.  Logging is nice, but not critical 
                }
                catch (SqlException ex)
                {
                    WriteLogConsole("SqlException=" + ex.ToString());
                    // don't stop, keep going.  Logging is nice, but not critical 
                }
                catch (Exception ex)
                {
                    WriteLogConsole("System.Exception=" + ex.Message);
                    // don't stop, keep going.  Logging is nice, but not critical 
                }

            }

The short version of the error thrown is this:

Unrecognized configuration section CustomAppSettings/LogExceptionsToFile

Full exception:

    SqlConnectionObj - about to open with SqlConnectionString='Server=abc;Database=MyDBName;Trusted_Connection=true'
    Exception thrown: 'System.TypeInitializationException' in System.Data.dll
    TypeInitializationException=System.TypeInitializationException: The type initializer for 'System.Data.SqlClient.SqlConnection' threw an exception. ---> System.TypeInitializationException: The type initializer for 'System.Data.SqlClient.SqlConnectionFactory' threw an exception. ---> System.TypeInitializationException: The type initializer for 'System.Data.SqlClient.SqlPerformanceCounters' threw an exception. ---> System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize ---> System.Configuration.ConfigurationErrorsException: Unrecognized configuration section CustomAppSettings/LogExceptionsToFile
     at System.Configuration.ConfigurationSchemaErrors.ThrowIfErrors(Boolean ignoreLocal)
   at System.Configuration.BaseConfigurationRecord.ThrowIfParseErrors(ConfigurationSchemaErrors schemaErrors)
   at System.Configuration.BaseConfigurationRecord.ThrowIfInitErrors()
   at System.Configuration.ClientConfigurationSystem.EnsureInit(String configKey)
   --- End of inner exception stack trace ---
   at System.Configuration.ConfigurationManager.PrepareConfigSystem()
   at System.Configuration.ConfigurationManager.GetSection(String sectionName)
   at System.Configuration.PrivilegedConfigurationManager.GetSection(String sectionName)
   at System.Diagnostics.DiagnosticsConfiguration.GetConfigSection()
   at System.Diagnostics.DiagnosticsConfiguration.Initialize()
   at System.Diagnostics.DiagnosticsConfiguration.get_SwitchSettings()
   at System.Diagnostics.Switch.InitializeConfigSettings()
   at System.Diagnostics.Switch.InitializeWithStatus()
   at System.Diagnostics.Switch.get_SwitchSetting()
   at System.Data.ProviderBase.DbConnectionPoolCounters..ctor(String categoryName, String categoryHelp)
   at System.Data.SqlClient.SqlPerformanceCounters..ctor()
   at System.Data.SqlClient.SqlPerformanceCounters..cctor()
   --- End of inner exception stack trace ---
   at System.Data.SqlClient.SqlConnectionFactory..cctor()
   --- End of inner exception stack trace ---
   at System.Data.SqlClient.SqlConnection..cctor()
   --- End of inner exception stack trace ---
   at System.Data.SqlClient.SqlConnection..ctor(String connectionString)
   at WinSCPWrapperGet.Program.Main(String[] args)

I think it's related to something like this.

What do I have to change to make it happy? I saw other posts about using but I don't have a group. I added everything below in as an attempt to fix the issue. The rest of the program runs fine and uses the config file as desired.

<configuration>
  <configSections> <!-- this was not here when I first got the error, 
         me thinks I need something like to fix this issue -->
    <sectionGroup name="CustomAppSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <section name="MyApp.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
    </sectionGroup>
  </configSections>  
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
  </startup>
  <CustomAppSettings>
      <!-- we have many more parms, but here is an example; 
           each SFTP site can have about 10 config parms --> 
      <Site1>
         <add key="HostName" value="sftp.somesite1.com"/>
         <add key="HostPort" value=""/>
      </Site1>
      <Site2>
         <add key="HostName" value="sftp.somesite1.com"/>
         <add key="HostPort" value=""/>
      </Site2>
    ... etc...

NOTE: This is in production now, and I am enhancing it. We have maybe a few dozen config files in different scheduled tasks, so I would hate to change all of them, even if they are not designed perfectly.

Found this: https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/performance-counters

It tells us that we can tune the performance counters in the config file:

<system.diagnostics>
  <switches>
    <add name="ConnectionPoolPerformanceCounterDetail"
         value="4"/>
  </switches>
</system.diagnostics>

So bottom line, I just need to know how to make my config file work with SQL, even though the connection string in the config is not the issue.

NealWalters
  • 17,197
  • 42
  • 141
  • 251
  • *Why is sqlconnection.open nosing around in my config file?* - something looking for logging settings? You're seemingly under the assumption it's looking for the conn str, even though you've hard coded it.. Why? – Caius Jard May 13 '22 at 21:23
  • Because it says "Unrecognized configuration section CustomAppSettings" in the error. – NealWalters May 13 '22 at 21:28
  • @CaiusJard Like SqlPerformanceCounters is looking at config file for some settings? – NealWalters May 13 '22 at 21:28
  • @CaiusJard Let me reword that, it's not looking for the connection string, it's look in the config file for other stuff, like maybe if there are any performance counters or instructions there for other parts of SQL that I don't care about. – NealWalters May 13 '22 at 21:43
  • Not sure what the long context is all about if you have the clear exception message. – Wiktor Zychla May 13 '22 at 21:45
  • @WiktorZychla - just looking how to fix my config file, or tell PerformanceCounters not to look there. I am about to add something else I found. – NealWalters May 13 '22 at 21:47
  • Is there the LogExceptionsToFile the exception mentions? Can you remove the section? Or there isn't anything like that in the config and you still get the exception? – Wiktor Zychla May 13 '22 at 21:52

1 Answers1

0

The group is not needed, so far the following has got around the original issue:

<configuration>
  <configSections>
      <section name="CustomAppSettings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
  </configSections>  
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
  </startup>
  <CustomAppSettings>
      etc... 

Reference: https://blog.ivankahl.com/creating-custom-configuration-sections-in-app-config/

NealWalters
  • 17,197
  • 42
  • 141
  • 251