You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Framework4.8 WinForms程序服务器运行配置错误排查求助

问题:.NET Framework 4.8升级后任务计划运行报错ConfigurationErrorsException

将Windows Forms应用升级至.NET Framework 4.8后,Visual Studio调试运行正常,但服务器以任务计划形式运行时抛出System.Configuration.ConfigurationErrorsException,运行任务的用户对安装目录拥有完全权限,需排查问题原因。

报错信息

Application: DirectoryLister.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Configuration.ConfigurationErrorsException
   at System.Configuration.BaseConfigurationRecord.EvaluateOne(System.String[], System.Configuration.SectionInput, Boolean, System.Configuration.FactoryRecord, System.Configuration.SectionRecord, System.Object)
   at System.Configuration.BaseConfigurationRecord.Evaluate(System.Configuration.FactoryRecord, System.Configuration.SectionRecord, System.Object, Boolean, Boolean, System.Object ByRef, System.Object ByRef)
   at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(System.String, Boolean, Boolean, Boolean, Boolean, System.Object ByRef, System.Object ByRef)
   at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(System.String, Boolean, Boolean, Boolean, Boolean, System.Object ByRef, System.Object ByRef)
   at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(System.String, Boolean, Boolean, Boolean, Boolean, System.Object ByRef, System.Object ByRef)
   at System.Configuration.BaseConfigurationRecord.GetSection(System.String)
   at System.Configuration.ConfigurationManager.get_ConnectionStrings()
   at DirectoryLister.Form1..ctor()

Exception Info: System.InvalidOperationException
   at DirectoryLister.My.MyProject+MyForms.Create__Instance__[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](System.__Canon)
   at DirectoryLister.My.MyProject+MyForms.get_Form1()
   at DirectoryLister.My.MyApplication.OnCreateMainForm()
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(System.String[])
   at DirectoryLister.My.MyApplication.Main(System.String[])

应用配置文件

<?xml version="1.0"?>
<configuration >
  <connectionStrings>
    <add name="LBConn" connectionString="Data Source=DEVSQL2;Initial Catalog=LiveBait;Integrated Security=True" providerName="System.Data.SqlClient" />
  </connectionStrings>
  <appSettings>
    <add key="FMS" value="\VMFMS\FMS\" />
    <add key="FILEMOD" value="C:\Program Files (x86)\American Share Insurance\Application Modification App"  />
    <add key="FMS_REPORTS" value="\VMFMS\FMS_REPORTS\" />
    <add key="ClientSettingsProvider.ServiceUri" value="" />
  </appSettings>
  <system.diagnostics>
    <sources>
      <!-- This section defines the logging configuration for My.Application.Log -->
      <source name="DefaultSource" switchName="DefaultSwitch">
        <listeners>
          <add name="FileLog" />
          <!-- Uncomment the below section to write to the Application Event Log -->
          <!--<add name="EventLog"/>-->
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="DefaultSwitch" value="Information" />
    </switches>
    <sharedListeners>
      <add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter" />
      <!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
      <!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
    </sharedListeners>
  </system.diagnostics>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
  </startup>
  <system.web>
    <membership defaultProvider="ClientAuthenticationershipProvider">
      <providers>
        <add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
      </providers>
    </membership>
    <roleManager defaultProvider="ClientRoleProvider" enabled="true">
      <providers>
        <add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
      </providers>
    </roleManager>
  </system.web>
</configuration>

Form1.vb代码

Imports System
Imports System.IO
Imports System.Text
Imports System.Data.Sql
Imports System.Data.SqlClient
Imports System.Configuration


Public Class Form1
    'Private _stringBuilder As StringBuilder = New StringBuilder
    Dim ocmd As SqlCommand
    Dim reader As SqlDataReader
    Dim oConn As New SqlConnection(ConfigurationManager.ConnectionStrings("LBConn").ToString)
    Dim dModifiedStart As Date = DateAdd(DateInterval.Day, -1, Now()).ToString("MM/dd/yyyy 00:00")
    Dim dModifiedEnd As Date = DateAdd(DateInterval.Day, -1, Now()).ToString("MM/dd/yyyy 23:59:59")
    Dim strLastModified As String
    Dim strFileLocation As String
    Dim strFileName As String
    Dim strFileExtension As String
    Dim list As New List(Of String)

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Try
            Application.DoEvents()

            Dim fs As New FileStream(System.Environment.CurrentDirectory & "\Running.txt", FileMode.Create, FileAccess.Write)
            'declaring a FileStream and creating a word document file named file with 
            'access mode of writing
            Dim s As New StreamWriter(fs)
            'creating a new StreamWriter and passing the filestream object fs as argument
            s.BaseStream.Seek(0, SeekOrigin.End)
            'the seek method is used to move the cursor to next position to avoid text to be
            'overwritten
            s.WriteLine("This is program is currently running.")
            'writing text to the newly created file
            s.Close()
            'closing the file

            'Added: July 11, 2013
            'Parse Exclusion file so we know which file extentions that must be ignored
            'The purpose of putting it in a text file is we can then change the text file without changing the EXE code

            Using File = System.IO.File.OpenText(System.Environment.CurrentDirectory & "\FileExclusion.txt")
                While Not File.endofstream
                    Dim line As String = File.readline()

                    list.Add(line)
                End While
            End Using


            oConn.Open()

            For Each appSetting As String In ConfigurationManager.AppSettings.AllKeys
                Dim appSettingValue = ConfigurationManager.AppSettings.Get(appSetting)
                'Pass in the directory name and the site which we are monitoring
                PrintFiles(appSettingValue, appSetting)
            Next
        Catch ex As Exception
            Call WriteLog("Main_Load: " & ex.Message)
        Finally
            oConn.Close()
        If File.Exists("Running.txt") Then
            File.Delete("Running.txt")
        End If
        Call WriteLog("---------------------------------------------")
        End Try

        Me.Close()
    End Sub

    Private Function PrintFiles(ByVal root As String, ByVal site As String) As String
        'Write all the files in this folder        
        For Each fileName As String In Directory.GetFiles(root)
            'MsgBox(Path.GetExtension(fileName).ToString)
            strFileExtension = Path.GetExtension(fileName).ToString

            If (Not Path.GetFullPath(fileName) Like "*_vti*" And _
                Not Path.GetFullPath(fileName) Like "*_private" And _
                Not Path.GetFullPath(fileName) Like "*pdf" And _
                Not Path.GetFullPath(fileName) Like "*NoteFiles" And _
                Not Path.GetFullPath(fileName) Like "*$tf" And _
                Not Path.GetFullPath(fileName) Like "*cfxtemp") Then

                If Not list.Contains(strFileExtension) Then
                    strLastModified = System.IO.File.GetLastWriteTime(fileName).ToString("MM/dd/yyyy hh:mm tt")

                    'check to see if the file has changed the previous day if so then add to database
                    If DateDiff(DateInterval.Day, CDate(strLastModified), dModifiedStart) >= 0 _
                        And DateDiff(DateInterval.Day, CDate(strLastModified), dModifiedEnd) <= 0 Then
                        If site = "FMS" Then
                            If Path.GetDirectoryName(fileName).Substring(0, 2) = "\\" Then
                                strFileLocation = Replace(Path.GetDirectoryName(fileName).ToString, "\\", "", 1, 1)
                                strFileLocation = Replace(strFileLocation, "VMFMS\FMS", "T:\")
                                strFileLocation = Replace(strFileLocation, "\\", "\")
                            End If
                        Else
                            strFileLocation = Path.GetDirectoryName(fileName)
                        End If

                        strFileName = Path.GetFileName(fileName)

                        'We do not need to grab the log file and add it as it will be changing nightly
                        If Not strFileName = "DirectoryLister.exe_LogFile.txt" Then
                            'add record to the database
                            Dim ocmd As New SqlCommand("sp_apFileChanges", oConn)
                            ocmd.CommandType = CommandType.StoredProcedure
                            With ocmd.Parameters
                                .Add(New SqlParameter("@FileName", strFileName))
                                .Add(New SqlParameter("@FileLocation", strFileLocation))
                                .Add(New SqlParameter("@ModifiedDate", strLastModified))
                                .Add(New SqlParameter("@Site", site))
                            End With
                            ocmd.ExecuteNonQuery()
                        End If
                    End If
                End If
            End If

        Next
        'If there are directories in this folder process them        
        For Each foundDir As String In Directory.GetDirectories(root)
            Try
                PrintFiles(foundDir, site)
            Catch ex As Exception
                Call WriteLog("PrintFiles: " & ex.Message)
            End Try
        Next
        Return "Done"
    End Function

    Public Sub WriteLog(ByVal sLogEntry As String)
        Dim objStreamWriter As StreamWriter

        'Pass the file path and the file name to the StreamWriter constructor.
        objStreamWriter = New StreamWriter(Application.ExecutablePath & "_LogFile.txt", True)

        'Write a line of text.
        objStreamWriter.WriteLine(Date.Now.ToLongDateString & vbTab & Date.Now.ToLongTimeString & vbTab & sLogEntry)

        'Close the file.
        objStreamWriter.Close()
    End Sub
End Class

排查分析与解决方法

从报错栈可知,异常发生在Form1构造函数读取ConfigurationManager.ConnectionStrings("LBConn")时,结合任务计划的运行场景,可能的原因及解决方式如下:

1. 配置文件读取路径异常

任务计划运行时,当前工作目录不一定是程序安装目录,导致ConfigurationManager无法找到正确的.config文件,或者依赖的FileExclusion.txt无法读取。

  • 解决:替换所有System.Environment.CurrentDirectory为Path.GetDirectoryName(Application.ExecutablePath),确保始终从程序安装目录读取文件;同时确认DirectoryLister.exe.config和FileExclusion.txt都在安装目录下,任务用户有读取权限。

2. .NET Framework版本兼容性问题

虽然配置文件指定了.NETFramework,Version=v4.8,但服务器可能未正确安装该版本,或任务计划默认加载的.NET版本不符。

  • 解决:
    • 检查服务器是否安装.NET Framework 4.8:打开注册表,查看HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full下的Release值是否为528040或更高。
    • 确保任务计划的程序启动环境优先使用.NET 4.8,可通过修改服务器的.NET版本优先级设置实现。

3. 数据库集成身份验证权限不足

连接字符串使用Integrated Security=True,任务计划运行的用户可能没有访问DEVSQL2数据库的权限(即使对安装目录有完全权限)。

  • 解决:
    • 测试任务用户是否能通过SSMS连接到DEVSQL2的LiveBait数据库。
    • 若权限不足,可改为使用SQL Server账号密码的连接字符串,或给任务用户分配数据库访问权限。

4. 配置文件格式或内容错误

服务器上的配置文件可能存在编码问题、XML格式错误,或被篡改。

  • 解决:对比调试环境和服务器上的DirectoryLister.exe.config内容,确保完全一致;使用XML验证工具检查配置文件语法是否合法。

5. 构造函数中初始化数据库连接的时机问题

当前代码在类级别变量中直接初始化oConn,此时配置文件可能尚未完全加载,导致读取失败。

  • 解决:将数据库连接的初始化移到Form1_Load方法中:
    ' 类级别仅声明变量
    Dim oConn As SqlConnection
    
    ' 在Form1_Load中初始化
    Private Sub Form1_Load(...)
        Try
            oConn = New SqlConnection(ConfigurationManager.ConnectionStrings("LBConn").ToString)
            ' 其他代码...
    

内容的提问来源于stack exchange,提问作者rgorr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:17:34