当.NET 4应用程序中的AccessViolationException违反MSDN记录的行为时该怎么办?

时间:2016-09-07 20:55:10

标签: c# ssis access-violation

我将一个.NET 4应用程序编写为Windows服务,其中包含非托管组件,并且正在向我的log4net日志打印AccessViolationException,但不会导致应用程序崩溃。关于这个问题的一切听起来都不可能以下是我认为正在发生的事情,我想知道我的下一步应该是开发人员应该做什么的?在与生产相同的数据源的并行重放环境中不会发生此问题。

  1. 内存损坏问题表现为AccessViolationException,堆栈跟踪指责SSIS运行时“DTS”。
  2. DataLoaderWinSvc.exe是一个.NET 4应用程序,已注册/运行为Windows本地服务。
  3. Microsoft在.NET 4中更改了CLR,因此默认情况下AccessViolationException会导致应用程序崩溃。
  4. 然而,DataLoaderWinSvc.exe不会崩溃。这导致我调查这可能是怎么回事?
  5. 有一种方法可以让开发人员在.NET 4中处理异常,但DataLoaderWinSvc.exe代码没有使用[HandleProcessCorruptedStateExceptions]技术。 https://msdn.microsoft.com/en-us/library/system.accessviolationexception(v=vs.110).aspx#Anchor_6
  6.   

    从.NET Framework 4开始,AccessViolationException   公共语言运行库抛出的异常不由处理   如果异常,结构化异常处理程序中的catch语句   发生在公共语言运行库保留的内存之外。   要处理此类AccessViolationException例外,您应该申请   HandleProcessCorruptedStateExceptionsAttribute属性   抛出异常的方法。

    1. 基于DataLoaderWinSvc.txt log4net日志,显然DataLoaderWinSvc.exe能够处理此异常,尽管作为.NET Framework 4应用程序运行,否则我们将不会有任何日志记录语句而且会崩溃。但是,根本没有崩溃。
    2. 通过使用Process Explorer.exe,我查看是否可能以某种方式部署的代码版本不是使用.NET 4 Framework。 - 这是我开始看到可疑的地方!事实证明,SSIS运行时DLL,d:\ Program Files(x86)\ Microsoft SQL Server \ 120 \ SDK \ Assemblies \ Microsoft.SQLServer.ManagedDTS.dll,是一个.NET 2.0程序集。
    3. 看来,基于Process Explorer.exe,我调用的Microsoft.SQLServer.ManagedDTS.dll是一个.NET 4程序集,它实际上将工作委托给一个带有本机的CLR v2.0.50727程序集image(ngen'd assembly)。
    4. 如果在CLR v2.0.50727程序集中发生AccessViolationException,那么这可能就是我们如何能够捕获这个据称无法捕获的异常。
    5.   

      这是匿名堆栈跟踪:

           

      2016-08-16 20:58:38,207错误:编排:初始化   System.AccessViolationException:尝试读取或写入受保护的   记忆。这通常表明其他记忆已损坏   在Microsoft.SqlServer.Dts.Runtime.Package.Execute()at   DataLoader.Orchestration.DoWork()in   D:\ SourceCode \ DataLoader \ Mainline \ Core \ Orchestration.cs:第198行   System.AccessViolationException:尝试读取或写入受保护的   记忆。这通常表明其他记忆已损坏   在Microsoft.SqlServer.Dts.Runtime.Package.Execute()at   DataLoader.Orchestration.DoWork()in   D:\ SourceCode \ DataLoader \ Mainline \ Core \ Orchestration.cs:第198行

      这里大致是一段近似代码正在做的代码:

      public class Orchestration
      {
        private Application m_DTSApplication;
        private Package m_DTSPackage;
      
        public IntradayOrchestration()
        {
          InitializeDTSPackage();
        }
      
        private void InitiatlizeDTSPackage()
        {
          m_DTSPackageLocation = ConfigurationManager.AppSettings["DTSPackageLocation"].ToString();
          m_DTSPackageConfigLocation = ConfigurationManager.AppSettings["DTSPackageConfigLocation"].ToString();
      
          m_DTSApplication = new Application();
          m_DTSApplication.PackagePassword = ConfigurationManager.AppSettings["DTSPackagePassword"];
      
          m_DTSPackage = m_DTSApplication.LoadPackage(m_DTSPackageLocation, null);
          m_DTSPackage.ImportConfigurationFile(m_DTSPackageConfigLocation);       
        }
      
        private void DoWork()
        {
          try
          {
            Stopwatch sw = Stopwatch.StartNew();
            while (true)
            {
              sw.Start();
              DTSExecResult result = m_DTSPackage.Execute();                                           
              sw.Stop();
              Logger.ReportInfo(DateTime.Now.ToString() + "Time taken by dts package= " + sw.ElapsedMilliseconds.ToString());
      
              // Check retuns status and check for errors on Job execution
              if (result != DTSExecResult.Success || m_DTSPackage.Errors != null)
              {
                if (m_DTSPackage.Errors != null)
                {
                  foreach (DtsError error in m_DTSPackage.Errors)
                  {
                    string errorMesg = string.Format("Orchestration: SSIS Package [{0}] Error: Code[{1}] Source[{2}] Component[{3}] Description[{4}]", m_DTSPackage.Name, error.ErrorCode, error.Source, error.SubComponent, error.Description);
                    Logger.ReportError(errorMesg, new ApplicationException(errorMesg));
                  }
                }
                else
                {
                  string errorMesg = string.Format("Orchestration: SSIS Package [{0}] did not complete successfully. Return status [{1}]", m_DTSPackage.Name, result.ToString());
                  Logger.ReportError(errorMesg, new ApplicationException(errorMesg));
                }
              }
              else
              {
                Logger.ReportInfo(
                  string.Format("Orchestration: SSIS Package [{0}] completed successfully", m_DTSPackage.Name));
              }
           }
           catch (Exception ex)
           {
              Logger.ReportError(
                  string.Format("Orchestration: SSIS Package [{0}] completed successfully", m_DTSPackage.Name));
           }
        }
      }
      

1 个答案:

答案 0 :(得分:0)

由于跨越.NET 4到.NET 2的运行时环境,根本原因实际上是“空域”。

另外,事实证明,SQL Server 2008 R2 SSIS Runtime可能在SQL日志记录子组件中存在双重可用内存错误。