65.9K
CodeProject 正在变化。 阅读更多。
Home

快速解决生产问题

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (8投票s)

2015 年 11 月 10 日

CPOL

8分钟阅读

viewsIcon

31675

使用 PDB 文件,使用远程调试工具

引言

开发人员面临的最主要问题之一是生产环境发生问题。开发人员必须快速找到问题的根本原因,或者在开发环境中重现相同的问题以解决它。由于时间至关重要,延迟找到根本原因可能会给客户带来经济损失,或导致公司声誉受损。有几种方法可以高效且快速地解决生产环境中的问题。

调试问题的方法

  1. 通过日志查看调用堆栈
  2. 启用跟踪并检查跟踪输出
  3. 在开发环境中重现场景并使用 Visual Studio 进行调试
  4. 使用程序数据库 (PDB) 文件
  5. 远程调试

1. 通过日志查看调用堆栈

这是最常见的调试问题的方法,即获取用户的日志文件并检查其中的异常。如果异常已知且已用自定义消息处理,则很有用,但如果异常是未处理的,则很难找出异常是如何发生的。调用堆栈在此方法中很有用,但调用堆栈仍然提供方法级别的信息。方法级别的信息无法显示确切是哪一行导致了问题。要获取确切的行信息,我们需要将程序数据库 (PDB) 文件与应用程序一起使用。PDB 文件将在下面详细介绍。日志的另一个缺点是,我们无法在应用程序中进行大量日志记录,尤其是在日志写入输出文件的情况下。这会极大地降低应用程序的性能。因此,日志记录应保持有限,并按需进行。

2. 启用跟踪并检查跟踪输出

可以通过配置启用跟踪,然后重新运行应用程序以检查跟踪输出。如果禁用跟踪,程序将忽略 Trace 语句。因此,可以在代码中包含带有跟踪开关的 Trace 语句。但此方法仍然存在限制,因为它需要为每个逻辑代码编写,这维护起来有点麻烦。

3. 在开发 (Dev) 环境中重现场景并使用 Visual Studio 进行调试

由于一种常见的做法是仅在客户机上部署程序集(编译后的代码)和框架,因此很明显,客户机上没有应用程序代码或 Visual Studio IDE/调试器用于调试目的。因此,为了找到根本原因,开发人员需要设置开发环境并重现类似场景,并在开发人员的机器上进行调试。

这是找到问题根本原因的最可靠的方法,但存在严重限制。

  1. 开发和生产环境中的数据可能不相同,因此数据相关的问题难以重现。
  2. 这是一个耗时的工作,考虑到重现问题的紧迫性,在开发环境中设置可能很难,具体取决于应用程序运行所涉及的多个系统。

4. 使用程序数据库 (PDB) 文件

这是在客户机上调试问题的最简单方法。但 PDB 文件是什么?当应用程序编译时,我们通常会在 bin 文件夹中看到它们。即使它们不存在,程序也可以运行,那么它们携带了什么信息?

  • PDB 文件:程序数据库文件也称为符号文件,包含代码的调试信息,例如:
    • 全局变量
    • 局部变量
    • 函数名称及其入口点的地址
    • 帧指针省略 (FPO) 记录
    • 源行号 (参考 MSDN)

因此,可以更丰富地获取堆栈跟踪。当我们随 EXE/DLL 一起包含 PDB 文件并重现场景时,当前的堆栈跟踪还将提供错误发生的行号。这有助于我们确切地了解错误发生在哪里,然后进行纠正或提供修复。让我们通过一个例子来展示 PDB 文件的用法。

让我们创建一个名为“ProdProject”的简单控制台项目和一个名为“DataLayer”的类库。DataLayer 类库有一个名为 SaveIntoDatabaseDatabaseOperations 类。

DatabaseOperations.cs

namespace DataLayer
{
    public class DatabaseOperations
    {
        public void SaveIntoDatabase(string Name,string MathsMarks,string ScienceMarks)
        {

            int Maths = Convert.ToInt32(MathsMarks);
            int Science = Convert.ToInt32(ScienceMarks);
            // Code to insert values into the database 
        }       
    }
}

Program.cs

namespace SymbolProject
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string[] arrValues = new string[3];

                Console.Write("Name:");
                string Name = Console.ReadLine();
                Console.Write("Maths Marks:");
                string MathsMarks = Console.ReadLine();
                Console.Write("Science Marks:");
                string ScienceMarks = Console.ReadLine();

                DataLayer.DatabaseOperations dbOperation = new DataLayer.DatabaseOperations();
                dbOperation.SaveIntoDatabase(Name, MathsMarks, ScienceMarks);
                Console.Write("Data inserted successfully");
                Console.ReadLine();
            }
            catch(Exception ex)
            {
                Console.WriteLine("Message:" + ex.Message + 
			Environment.NewLine + "StackTrace:" + ex.StackTrace);
                Console.ReadLine();
            }
        }
    }
  }

发布模式下构建应用程序之前,我们需要启用 PDB 文件的创建。

这可以通过在解决方案资源管理器中右键单击 DataLayer 项目 => 属性 => 生成 => 高级 => 调试信息 => 仅 PDB 来完成。

这里有 3 个选项

  • 无 – 不会创建 pdb 文件
  • 仅 PDB – 符号仅存储在 pdb 文件中
  • 完整 – 符号将存储在 pdb 文件和程序集中

\bin\Release 中,您将看到创建了以下文件

  1. DataLayer.dll
  2. DataLayer.pdb
  3. ProdApplication.exe

现在您可以将 DataLayer.dllProdApplication.exe 部署到客户。

(没有 PDB 文件) 如果错误发生在客户机上,将看到以下输出

您会看到堆栈跟踪显示了发生错误的方法名称,但仍然不知道方法中的具体位置。即 DataLayer.DatabaseOperation.SaveIntoDatabase

现在,如果您在 EXE 位置提供了 PDB 文件 (DataLayer.pdb) 并在客户机上重新运行应用程序,您将看到以下输出

这里,它显示了方法名称,即 DataLayer.DatabaseOperation.SaveIntoDatabase,并且还提到了错误发生的行号,即第 15 行。

如果您转到源代码并检查这一行,您将看到哪段代码有问题,并为此问题提供修复。

非常重要:PDB 文件是 DLL/EXE 的特定于版本的。它们包含链接到相应 DLL/EXE 的 GUID。因此,一个版本的 PDB 文件不能与另一个版本的 DLL/EXE 一起使用,即使代码没有改变。因此,一旦您在发布模式下创建了一个版本,您就需要将该 PDB 存储在某个存储库中,称为“符号服务器”。提供 PDB 作为发布版本是可选的。但提供它并没有多大风险,因为您的程序集和 EXE 已经包含了您的源代码。反编译您的可执行文件是可能的,并且可能需要类似的努力来处理 PDB 文件。总而言之,除非您的安装包有大小限制,否则问题不大,因为 PDB 文件会占用大量空间。

5. 远程调试

PDB 文件是开始调试的好方法,但如果您可以连接到客户机,则可以从您的机器上调试应用程序。远程调试的实现相当简单。您只需要做以下几件事

您需要在客户机上设置远程调试工具。

这些工具可以在 Microsoft 网站上找到,例如 https://www.microsoft.com/en-us/download/details.aspx?id=48155。URL 可能会更改,因此最好搜索“Remote Tools for Visual Studio 20XX”。

  1. 要安装远程调试工具,用户需要管理员权限。
  2. 安装并打开应用程序后,您将看到以下窗口。该窗口要求您配置远程调试以允许防火墙连接到此计算机。单击配置远程调试。

    单击后,您将看到

    METADOR”是我的服务器主机名。4020 是托管此服务的端口号。

  3. 单击工具 => 选项 => 权限,如果两台计算机共享相同的活动目录,则设置用户,或选择“无身份验证”。

  4. 现在,在客户机上运行应用程序。不要继续操作,但在此之前,我们需要在 Visual Studio 调试器中附加此进程。
  5. 完成此操作后,您已在客户机上设置了远程调试器。现在是时候发现客户机并将您的 Visual Studio 调试器附加到那里运行的应用程序进程了。
  6. 为此,请使用您想要调试的应用程序代码打开 Visual Studio。转到调试 => 附加到进程。
  7. 选择传输为“远程(无身份验证)”[如果如步骤 3 中所述没有身份验证],然后单击查找。

    它将搜索主机名显示的服务器/客户机。这里是“METADOR”,然后单击选择。

  8. 在进程窗口中选择应用程序,然后单击附加。现在进程已附加,您可以对代码设置调试点。现在可以从您的机器上逐步调试用户输入的输入。

  9. 附加进程后,您需要检查符号文件是否已正确加载。当您尝试设置断点时,您会看到以下错误,从而可以观察到这一点

    要解决此问题,请转到调试 => 窗口 => 模块

    您可以看到 ProdApplication.exeDataLayer.dll 的符号未加载。如果符号未加载,则无法使用断点进行调试。

    要解决此问题,您可以右键单击模块中的 DataLayer.dll 并选择加载符号选项。这将弹出一个对话框来搜索 pdb 文件。找到该版本的 PDB 文件并加载它。

    如果为其创建了 ProdApplication.exe,也请对其执行类似操作。加载后,您将在模块中看到符号状态为“已加载符号”。

    在客户机 (METADOR) 上:输入可以重现场景的值。

    在程序员机器上

    按 F11。

这就是开发人员如何加快应用程序调试过程并提供快速响应。还有其他一些方法,例如分析应用程序内存转储并找出崩溃或内存泄漏的原因。但我将它们排除在本文的讨论范围之外,也许我可以在下一部分中介绍。

参考文献

以下参考文献非常全面且非常有用,如果您有时间,请务必阅读

Coding is Simple

© . All rights reserved.