.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版本优先级设置实现。
- 检查服务器是否安装.NET Framework 4.8:打开注册表,查看
3. 数据库集成身份验证权限不足
连接字符串使用Integrated Security=True,任务计划运行的用户可能没有访问DEVSQL2数据库的权限(即使对安装目录有完全权限)。
- 解决:
- 测试任务用户是否能通过SSMS连接到
DEVSQL2的LiveBait数据库。 - 若权限不足,可改为使用SQL Server账号密码的连接字符串,或给任务用户分配数据库访问权限。
- 测试任务用户是否能通过SSMS连接到
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
相关产品推荐
相关产品推荐

