如何识别 DLL 是否为 Debug 或 Release 构建(在 .NET 中)

119

这篇博客文章提供了编程方法,用于判断一个.NET程序集是Debug还是Release。 - Promit
这是关于同一主题的另一个SO问题的链接 - Graeme Bradbury
在Stackoverflow上有很多类似的问题,其中一个问题是如何在.NET中编程检测发布/调试模式,而且有许多不同的答案: https://dev59.com/LHRB5IYBdhLWcg3wV196 https://dev59.com/c3RA5IYBdhLWcg3w2x6W https://dev59.com/snVC5IYBdhLWcg3wvT_g https://dev59.com/fkXRa4cB1Zd3GeqPoxjd http://stackoverflow.com/questions/890459/asp-net-release-build-vs-debug-build - Kiquenet
也顺便提一句 - 我之前写过这个并包含各种编译选项的博客文章:http://completedevelopment.blogspot.com/2009/07/determining-if-assembly-is-compiled-in.html - Adam Tuliper
对于大多数人来说,可能行之有效的一种方法是使用记事本打开DLL/EXE文件,并查找路径,例如搜索"C:",您可能会发现类似"C:\Source\myapp\obj\x64\Release\myapp.pdb"这样的路径,“Release”表示使用了发布配置构建。 - Shahin Dohan
2个回答

122
在我看来,上述应用程序非常具有误导性;它只寻找IsJITTrackingEnabled,这与代码是否编译为优化和JIT优化完全无关。
如果您以发布模式编译并选择DebugOutput为“none”以外的任何内容,则存在DebuggableAttribute。
您还需要确切地定义“Debug”与“Release”的含义...
您是指该应用程序配置了代码优化吗? 您是指您可以将VS/JIT调试器附加到它上面吗? 您是指它生成DebugOutput吗? 您是指它定义了DEBUG常量吗?请记住,您可以使用System.Diagnostics.Conditional()属性有条件地编译方法。
在我看来,当有人询问一个程序集是否为“Debug”或“Release”时,他们真正想知道的是代码是否经过了优化...
那么,你想手动还是自动进行呢?
手动: 您需要查看程序集元数据的DebuggableAttribute位掩码的值。以下是如何执行此操作:
1.在ILDASM中打开程序集 2.打开清单 3.查看DebuggableAttribute位掩码。如果未出现DebuggableAttribute,则肯定是已优化的程序集。 4.如果出现,请查看第四个字节-如果是“0”,则为JIT优化-其他任何内容都不是:
// Metadata version: v4.0.30319 .... // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 02 00 00 00 00 00 )
自动:假设您想以编程方式知道代码是否进行了JIT优化,则以下是正确的实现(在简单的控制台应用程序中):
void Main()
{
    var HasDebuggableAttribute = false;
    var IsJITOptimized = false;
    var IsJITTrackingEnabled = false;
    var BuildType = "";
    var DebugOutput = "";
    
    var ReflectedAssembly = Assembly.LoadFile(@"path to the dll you are testing");
    object[] attribs = ReflectedAssembly.GetCustomAttributes(typeof(DebuggableAttribute), false);

    // If the 'DebuggableAttribute' is not found then it is definitely an OPTIMIZED build
    if (attribs.Length > 0)
    {
        // Just because the 'DebuggableAttribute' is found doesn't necessarily mean
        // it's a DEBUG build; we have to check the JIT Optimization flag
        // i.e. it could have the "generate PDB" checked but have JIT Optimization enabled
        DebuggableAttribute debuggableAttribute = attribs[0] as DebuggableAttribute;
        if (debuggableAttribute != null)
        {
            HasDebuggableAttribute = true;
            IsJITOptimized = !debuggableAttribute.IsJITOptimizerDisabled;
            
            // IsJITTrackingEnabled - Gets a value that indicates whether the runtime will track information during code generation for the debugger.
            IsJITTrackingEnabled = debuggableAttribute.IsJITTrackingEnabled;
            BuildType = debuggableAttribute.IsJITOptimizerDisabled ? "Debug" : "Release";

            // check for Debug Output "full" or "pdb-only"
            DebugOutput = (debuggableAttribute.DebuggingFlags &
                            DebuggableAttribute.DebuggingModes.Default) !=
                            DebuggableAttribute.DebuggingModes.None
                            ? "Full" : "pdb-only";
        }
    }
    else
    {
        IsJITOptimized = true;
        BuildType = "Release";
    }

    Console.WriteLine($"{nameof(HasDebuggableAttribute)}: {HasDebuggableAttribute}");
    Console.WriteLine($"{nameof(IsJITOptimized)}: {IsJITOptimized}");
    Console.WriteLine($"{nameof(IsJITTrackingEnabled)}: {IsJITTrackingEnabled}");
    Console.WriteLine($"{nameof(BuildType)}: {BuildType}");
    Console.WriteLine($"{nameof(DebugOutput)}: {DebugOutput}");
}

我在我的博客上提供了这个实现:

如何判断程序集是Debug还是Release


2
该工具在 http://assemblyinformation.codeplex.com/ 上已更新,您可能需要修改您的答案。 - Tim Abell
3
我需要指出的是,现在您已经知道要找什么(这得感谢Black先生),有一些工具,例如JetBrains的Dot Peek,可以提供您这些信息。使用Dot Peek,您只需双击程序集资源管理器中的程序集本身(而不是程序集下的任何文件),即可显示他在其工具中检查的所有程序集属性,其中关键的两个属性是Debuggable属性和IsJITOptimizerDisabled缺失。 - David Yates
3
@CaitLANJenner,这是我编写的一个工具的一部分,它做的事情远不止这些。我考虑将其放在Git上。无论如何,在上面的代码中,用要检查的程序集实例替换"ReflectedAssembly"。您可以使用Assembly.LoadFrom(...)或旧版本(已弃用)的用法进行操作 - Assembly.Load(...),Assembly.LoadFile(...)或Assembly.LoadWithPartialName(...)。 - Dave Black
1
在dotnet core中无法工作...无论是发布版还是调试版,输出结果都相同:HasDebuggableAttribute为True;IsJITOptimized为False;BuildType为Debug;DebugOutput为Full。 - Sasha Bond
1
对于一个.NET Core 3.1应用程序,我在JetBrains dotPeek(免费反编译工具)中加载了DLL,双击程序集,并查找AssemblyConfiguration属性。对于Debug,它显示[assembly: AssemblyConfiguration("Debug")],而对于Release,它显示[assembly: AssemblyConfiguration("Release")] - Randy Burden
显示剩余4条评论

95

唯一最好的方法是检查编译后的程序集本身。这里有一个非常有用的工具叫做 '.NET Assembly Information' ,由 Rotem Bloom 在这里找到。安装后,它将与 .dll 文件关联并自动打开。安装完成后,您只需双击程序集即可打开,它将显示如下屏幕截图中列出的程序集详细信息。您可以在那里确定是否使用调试编译。


4
它已被证明是我们开发团队中非常棒的工具。太神奇了! - this. __curious_geek
很棒的工具。它解决了我的问题。非常感谢您的帮助 :) - santosh kumar patro
3
无法在Windows 10上运行,无法加载“Microsoft.Owin.*”。 - user908645
3
@user908645 可以在https://github.com/tebjan/AssemblyInformation找到更新的分支。我使用了.msi安装程序,在我的Win10机器上运行良好。 - Marc.2377
不错的工具!!!正在运行。 - Willy
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接