打开 SQL 服务器连接导致:System.AccessViolationException 试图读取或写入受保护的内存

Opening SQL Server Connection causes: System.AccessViolationException Attempted to read or write protected memory

全部,

环境: 服务器 OS:Windows 服务器 2012R2(64 位)

服务器硬件:使用虚拟化软件

基于 .net 框架构建的应用程序:4.6.1(编译=任何 CPU),WinForms 应用程序

我有一个连接到 SQL 服务器的应用程序。当应用程序尝试打开 SQL 服务器连接时,我得到 System.AccessViolationException (下面的堆栈跟踪)。这仅发生在该服务器上。该应用程序在其他 servers/workstations 上运行良好。我已经完成了以下测试 - 请阅读下文(在堆栈跟踪之后了解更多信息)。

异常详情:

    System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'


Application: UpdateCenter.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
   at SNINativeMethodWrapper.SNIPacketAllocate(System.Runtime.InteropServices.SafeHandle, IOType, IntPtr ByRef)
   at System.Data.SqlClient.SNIPacket..ctor(System.Runtime.InteropServices.SafeHandle)
   at System.Data.SqlClient.TdsParserStateObject.GetResetWritePacket()
   at System.Data.SqlClient.TdsParserStateObject.WriteSni(Boolean)
   at System.Data.SqlClient.TdsParserStateObject.WritePacket(Byte, Boolean)
   at System.Data.SqlClient.TdsParser.SendPreLoginHandshake(Byte[], Boolean)
   at System.Data.SqlClient.TdsParser.Connect(System.Data.SqlClient.ServerInfo, System.Data.SqlClient.SqlInternalConnectionTds, Boolean, Int64, Boolean, Boolean, Boolean, Boolean, Boolean, System.Data.SqlClient.SqlAuthenticationMethod, Boolean, System.Data.SqlClient.SqlAuthenticationProviderManager)
   at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(System.Data.SqlClient.ServerInfo, System.String, System.Security.SecureString, Boolean, System.Data.ProviderBase.TimeoutTimer, Boolean, Boolean, Boolean)
   at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(System.Data.SqlClient.ServerInfo, System.String, System.Security.SecureString, Boolean, System.Data.SqlClient.SqlConnectionString, System.Data.SqlClient.SqlCredential, System.Data.ProviderBase.TimeoutTimer)
   at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(System.Data.ProviderBase.TimeoutTimer, System.Data.SqlClient.SqlConnectionString, System.Data.SqlClient.SqlCredential, System.String, System.Security.SecureString, Boolean)
   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(System.Data.ProviderBase.DbConnectionPoolIdentity, System.Data.SqlClient.SqlConnectionString, System.Data.SqlClient.SqlCredential, System.Object, System.String, System.Security.SecureString, Boolean, System.Data.SqlClient.SqlConnectionString, System.Data.SqlClient.SessionData, System.Data.ProviderBase.DbConnectionPool, System.String, Boolean, System.Data.SqlClient.SqlAuthenticationProviderManager)
   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(System.Data.Common.DbConnectionOptions, System.Data.Common.DbConnectionPoolKey, System.Object, System.Data.ProviderBase.DbConnectionPool, System.Data.Common.DbConnection, System.Data.Common.DbConnectionOptions)
   at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(System.Data.ProviderBase.DbConnectionPool, System.Data.Common.DbConnection, System.Data.Common.DbConnectionOptions, System.Data.Common.DbConnectionPoolKey, System.Data.Common.DbConnectionOptions)
   at System.Data.ProviderBase.DbConnectionPool.CreateObject(System.Data.Common.DbConnection, System.Data.Common.DbConnectionOptions, System.Data.ProviderBase.DbConnectionInternal)
   at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(System.Data.Common.DbConnection, System.Data.Common.DbConnectionOptions, System.Data.ProviderBase.DbConnectionInternal)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(System.Data.Common.DbConnection, UInt32, Boolean, Boolean, System.Data.Common.DbConnectionOptions, System.Data.ProviderBase.DbConnectionInternal ByRef)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(System.Data.Common.DbConnection, System.Threading.Tasks.TaskCompletionSource`1<System.Data.ProviderBase.DbConnectionInternal>, System.Data.Common.DbConnectionOptions, System.Data.ProviderBase.DbConnectionInternal ByRef)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(System.Data.Common.DbConnection, System.Threading.Tasks.TaskCompletionSource`1<System.Data.ProviderBase.DbConnectionInternal>, System.Data.Common.DbConnectionOptions, System.Data.ProviderBase.DbConnectionInternal, System.Data.ProviderBase.DbConnectionInternal ByRef)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(System.Data.Common.DbConnection, System.Data.ProviderBase.DbConnectionFactory, System.Threading.Tasks.TaskCompletionSource`1<System.Data.ProviderBase.DbConnectionInternal>, System.Data.Common.DbConnectionOptions)
   at System.Data.SqlClient.SqlConnection.TryOpenInner(System.Threading.Tasks.TaskCompletionSource`1<System.Data.ProviderBase.DbConnectionInternal>)
   at System.Data.SqlClient.SqlConnection.TryOpen(System.Threading.Tasks.TaskCompletionSource`1<System.Data.ProviderBase.DbConnectionInternal>)
   at System.Data.SqlClient.SqlConnection.Open()
   at PrlSystems.ProductUpdateLibrary.Schema.Drivers.MsSql.SqlServerDataLayerDriver.OpenConnection(System.String)
   at PrlSystems.ProductUpdateLibrary.Schema.DataLayerUpdater.TestConnection(PrlSystems.ProductUpdateLibrary.Schema.DataLayerSettings, System.String ByRef)
   at PrlSystems.UpdateCenter.Forms.Wizard.DatabaseConnectionForm.ctlTestDatabaseConnectionWorker_DoWork(System.Object, System.ComponentModel.DoWorkEventArgs)
   at System.ComponentModel.BackgroundWorker.WorkerThreadStart(System.Object)
   at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr, System.Object[], System.Object, System.Object[] ByRef)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage, System.Runtime.Remoting.Messaging.IMessageSink)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()

导致此异常的行是:

connection.Open();

所以我决定远程连接并调试应用程序以查看使用了什么连接字符串(这是完全合法的连接字符串)。接下来,我编写了一个快速而肮脏的控制台应用程序,它使用相同的连接 string/using 创建一个 SQL 连接,相同的 SQL 连接对象和 运行 它在同一台服务器上并且它可以工作.

控制台应用程序和崩溃的应用程序之间的唯一区别是:

我不知道是什么导致了这个异常,我什至无法用我的控制台应用程序重现它。 任何帮助将不胜感激。

===================== 更新 1(测试结果)================= ====

  1. 我确实创建了另一个 winforms 应用程序,运行 为 SQL 服务器建立连接的代码并且工作正常,...然后我做了#2

  2. 我编辑了崩溃的应用 Program.cs 并添加了以下几行

     static void Main()
     {
         Application.EnableVisualStyles();
         Application.SetCompatibleTextRenderingDefault(false);
         // connection that causes access violation exception
         var conn = new SqlConnection();
         conn.ConnectionString = @"Server=.\sqlexpress;Connection Timeout=5;Integrated Security=True";
         conn.Open(); // <= Will get exception after this line executes!
         conn.Close(); 
     }
    

当应用程序运行时,我仍然遇到访问冲突异常。这看起来像是这个程序被诅咒或列入黑名单!

=====================更新2(测试结果)================= ====

全部,我已将整个应用程序精简为只有 Program.cs 文件,其中只有几行用于在 Main() 函数中连接到数据库(并且仅引用了几个标准程序集)。不过,当应用程序运行时,我看到了同样的异常。

然后我将它重新编译为 .net 2、3.5,它成功了! 当我切换到 .net 4 或更高版本时,异常又回来了。您可能会认为某些东西在服务器上安装不正确,但为什么其他 .net 4 应用程序工作 运行 完全相同的代码?

全部,

我找到了问题的根本原因: 对于任何以 .net 4.5 及更高版本为目标的应用,VS 中的 Build/Platform 目标下都有一个设置:

“首选 32 位”

默认情况下,当您创建应用程序时,它会被选中。我们的应用程序未选中此设置,导致我们的服务器出现访问冲突异常。检查设置是否解决了问题。

不过,我解决了这个问题...如果我需要使用此目标框架构建应用程序,我会担心怎么办: .net 4.5 > 我的应用 >= .net 4.0

由于此设置对于低于 .net 4.5 的任何东西都被禁用,我永远无法解决这个问题,除非我尝试修复我的服务器并从软件角度确定缺少或未正确安装的内容。这是这个盒子只是因为我们 运行 我们的软件在其他 servers/workstations 上运行良好。