【问题标题】:Embed pdb into assembly将 pdb 嵌入到程序集中
【发布时间】:2010-12-03 20:03:00
【问题描述】:

我希望我的应用程序能够以单个 .exe 文件的形式分发,但我希望能够获得带有源代码行号的漂亮错误报告(应用程序只需发送带有 exception.ToString() 和发生未处理的异常时的一些附加信息)。

有没有办法将 .pdb 嵌入到程序集中?

【问题讨论】:

    标签: .net deployment pdb-files


    【解决方案1】:

    我使用了以下AssemblyResolve 处理程序,然后嵌入了任何程序集的dll 和pdb。您可以将其设置为在需要依赖项之前在应用程序中首先运行的任何内容。

        private static void SetupEmbeddedAssemblyResolve()
        {
            // Based on http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx
            AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
            {
                var name = args.Name;
                var asmName = new AssemblyName(name);
    
                // Any retargetable assembly should be resolved directly using normal load e.g. System.Core issue: 
                // http://stackoverflow.com/questions/18793959/filenotfoundexception-when-trying-to-load-autofac-as-an-embedded-assembly
                if (name.EndsWith("Retargetable=Yes"))
                {
                    return Assembly.Load(asmName);
                }
    
                var executingAssembly = Assembly.GetExecutingAssembly();
                var resourceNames = executingAssembly.GetManifestResourceNames();
    
                var resourceToFind = asmName.Name + ".dll";
                var resourceName = resourceNames.SingleOrDefault(n => n.Contains(resourceToFind));
    
                if (string.IsNullOrWhiteSpace(resourceName)) { return null; }
    
                var symbolsToFind = asmName.Name + ".pdb";
                var symbolsName = resourceNames.SingleOrDefault(n => n.Contains(symbolsToFind));
    
                var assemblyData = LoadResourceBytes(executingAssembly, resourceName);
    
                if (string.IsNullOrWhiteSpace(symbolsName))
                { 
                    Trace.WriteLine(string.Format("Loading '{0}' as embedded resource '{1}'", resourceToFind, resourceName));
    
                    return Assembly.Load(assemblyData);
                }
                else
                {
                    var symbolsData = LoadResourceBytes(executingAssembly, symbolsName);
    
                    Trace.WriteLine(string.Format("Loading '{0}' as embedded resource '{1}' with symbols '{2}'", resourceToFind, resourceName, symbolsName));
    
                    return Assembly.Load(assemblyData, symbolsData);
                }
            };
        }
    
        private static byte[] LoadResourceBytes(Assembly executingAssembly, string resourceName)
        {
            using (var stream = executingAssembly.GetManifestResourceStream(resourceName))
            {
                var assemblyData = new Byte[stream.Length];
    
                stream.Read(assemblyData, 0, assemblyData.Length);
    
                return assemblyData;
            }
        }
    

    【讨论】:

    • 我也写了一篇简短的博文:codingmurmur.com/2014/02/…
    • 哇。我知道你可以用 dll 文件做到这一点,但这也适用于 pdb 文件?整洁的。这确实意味着,要使用它使项目成为单文件分发,您需要将主应用程序放入外部 dll 项目中。
    • 只有当您不希望主应用程序 pdb 位于 exe 旁边时。我们可以忍受。
    • 我确实说过一个单文件发行版;)
    【解决方案2】:

    您可以编写一个存根可执行文件,其中包含作为嵌入式资源的实际可执行文件及其 pdb 文件。启动 staub 可执行文件后,它会将真正的可执行文件和 pdb 提取到一个临时目录中并启动它。

    就像某些安装程序或其他应用程序一样。

    我不确定是否值得付出额外的努力。

    【讨论】:

    • 我也有这个想法。这也将让我对我的二进制文件应用压缩并使 .exe 更小。缺点是启动时间较长。我只是希望有一种更简单的方法来做到这一点。
    【解决方案3】:

    使用 MiniDumps 而不是“exception.ToString()”。它将为您提供更多信息,并且不需要将 .pdb 与 .exe 一起分发。

    有用链接:Post-Mortem Debugging Your Application with Minidumps and Visual Studio .NET

    【讨论】:

    • 当然可以,但是您需要保留您发布的每个构建的 PDB 以使其可靠地工作 - 最好在内部设置符号服务器(请参阅 msdn.microsoft.com/en-us/library/ms680693(VS.85).aspx)
    • 我可以对正在运行的应用程序进行小型转储吗?例如,如果我在 WinForms 中遇到未处理的异常,我将向用户显示错误对话框,其中包含发送错误报告和继续使用应用程序的选项(与终止应用程序相反)。
    猜你喜欢
    • 1970-01-01
    • 2010-10-08
    • 2012-06-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 2010-11-30
    • 1970-01-01
    • 2011-01-18
    相关资源
    最近更新 更多