Visual Studio 如何比较两个pdb文件并验证源代码是否匹配?

mzmfm0qo  于 2023-08-07  发布在  其他
关注(0)|答案(2)|浏览(163)

我想借助从Build 1和Build 2生成的.pdb文件验证两个版本之间是否存在源代码差异。
小背景:
我正在使用Visual Studio 2019,我的解决方案混合了.NET Framework,.NET Core项目,总计50个项目我希望有一种机制,通过比较build 1和build 2中的.dll和/或.pdb来验证源代码是否在两个版本之间发生了更改。
注:源代码构建的环境是相同的。

我想实现的目标:

每当源代码从版本X改变到版本Y时,计算机1构建整个解决方案,其结果是50个dll和50个pdb。我想跳过构建过程,只复制更改的dll和pdb,并在将源代码检出到版本Y后将其移植到计算机2以保存时间。
因此,我正在寻找的工具应该能够执行以下操作:
比较两个pdb的输出'true',如果源代码匹配,'false'是源代码中似乎有差异。另外:该工具还可以使用dll。

wribegjk

wribegjk1#

您可以使用Debug Interface Access SDK来达到您的需求。
特别是MS提供了一个使用IDiaDataSource::loadAndValidateDataFromPdb的示例
来自MS站点的报价:“.pdb文件同时包含签名和期限值。这些值会复制到与.pdb文件匹配的.exe或.dll文件中。在准备数据源之前,此方法将验证已命名的.pdb文件的签名和期限是否与提供的值匹配。”

eyh26e7m

eyh26e7m2#

正如官方文件所说:
符号文件的工作原理
pdb文件包含以下信息:
要在Visual Studio IDE中显示的源文件名和行号。
在应用程序中的何处停止断点。
所以我认为pdb将无法比较它们的源文件是否相同。因为它的内容没有足够的信息。
但是您仍然可以得到一个近似的结果(基于行号和偏移量)。
下面是一个控制台应用程序示例,以满足您的要求(我基于System.Reflection.Metadata):

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;

class Program
{
    static void Main(string[] args)
    {
        var pdbFile1 = "C:\\Users\\Administrator\\source\\repos\\Blazor-WebAssembly-by-Example\\Chapter09\\ConsoleApp1\\ConsoleApp1.pdb";
        var pdbFile2 = "C:\\Users\\Administrator\\source\\repos\\Blazor-WebAssembly-by-Example\\Chapter09\\ConsoleApp1\\test\\ConsoleApp1.pdb";
        var diff_pdb = "C:\\Users\\Administrator\\source\\repos\\Blazor-WebAssembly-by-Example\\Chapter09\\ConsoleApp1\\bin\\Debug\\net6.0\\ConsoleApp1.pdb";

        var sequencePoints1 = GetSequencePoints(pdbFile1);
        var sequencePoints2 = GetSequencePoints(diff_pdb);

        var areEqual = CompareSequencePoints(sequencePoints1, sequencePoints2);
        Console.WriteLine($"Are sequence points equal: {areEqual}");
    }

    static List<SequencePoint> GetSequencePoints(string pdbFilePath)
    {
        var sequencePoints = new List<SequencePoint>();

        using (var stream = File.OpenRead(pdbFilePath))
        {
            var pdbReaderProvider = MetadataReaderProvider.FromPortablePdbStream(stream);
            var pdbReader = pdbReaderProvider.GetMetadataReader();
            foreach (var methodDebugHandle in pdbReader.MethodDebugInformation)
            {
                var methodDebugInformation = pdbReader.GetMethodDebugInformation(methodDebugHandle);
                var sequencePointsForMethod = methodDebugInformation.GetSequencePoints();
                sequencePoints.AddRange(sequencePointsForMethod);
            }
        }

        return sequencePoints;
    }

    static bool CompareSequencePoints(List<SequencePoint> sequencePoints1, List<SequencePoint> sequencePoints2)
    {
        if (sequencePoints1.Count != sequencePoints2.Count)
        {
            return false;
        }

        for (int i = 0; i < sequencePoints1.Count; i++)
        {
            if (sequencePoints1[i].StartLine != sequencePoints2[i].StartLine ||
                sequencePoints1[i].EndLine != sequencePoints2[i].EndLine ||
                sequencePoints1[i].Offset != sequencePoints2[i].Offset)
            {
                return false;
            }
        }

        return true;
    }
}

字符串
上面的代码应该可以直接运行。

相关问题