【问题标题】:Detecting if a program was run by Visual Studio, as opposed to run from Windows Explorer检测程序是否由 Visual Studio 运行,而不是从 Windows 资源管理器运行
【发布时间】:2009-08-27 18:43:13
【问题描述】:

有没有办法检测您的程序是否是通过 Visual Studio 加载的,以及它是否作为独立的可执行文件启动?

我们的软件有一个错误报告功能来处理未处理的异常——我们需要能够将调试版本分发给我们的 Beta 测试人员,但我们不希望在开发过程中报告错误,因为如果 VS 使用完整的堆栈跟踪等捕获异常,则异常会更有用。

现在,如果 Application.ExecutablePath 包含 bin\Debug 或 bin\Release,我将禁用错误报告,但我认为可能有一种更可靠的方法来检测程序是否通过 VS 加载。

显然,我们可以使用一些预处理器宏设置不同的构建,但为了这个问题,假设这是不可能的——我不介意添加代码,但我正在尝试制作对构建过程的修改最少,这就是为什么命令行选项也是最后的手段。

如果重要的话,我使用的是 VS2003/.NET 1.1。

【问题讨论】:

    标签: c# visual-studio


    【解决方案1】:

    如果您这样做是为了确定它是否在 any 调试器中(由 @JaredPar 澄清),您可以在异常处理程序中使用 Debugger.IsAttached。

    try
    {
        // ...
    }
    catch(Exception ex)
    {
        if (!Debugger.IsAttached)
        {
            ExceptionHandler.Frob(ex);
        }
        else
        {
            throw;
        }
    }
    

    或者:

    public static void Frob(Exception ex)
    {
        if (Debugger.IsAttached)
        {
            Debugger.Break();
        }
    }
    

    【讨论】:

    • 这正是那些“我不知道我在寻找什么,但当我看到它时我会知道它”的答案之一 - 完美,谢谢!
    • 需要注意的一点是,它会告诉您是否附加了任何调试器,而不是是否附加了 Visual Studio。附加 WinDbg 会导致相同的行为。
    • 我们的“beta 测试人员”永远不会附加调试器;但如果他们这样做了,他们几乎会要求禁用错误报告功能:P
    • 请注意,如果您从 Visual Studio 以发布模式运行它,这将不起作用。如果您在调试模式下运行它但没有调试器(Ctrl + F5),这也将不起作用。
    【解决方案2】:

    我不进行 .net 开发,但在 java 中,我通过将标志传递给应用程序的启动选项来完成此操作。因此,您可以将调试标志从 IDE 传递到应用程序,然后检查它,当应用程序作为可执行文件运行时,该标志将不存在。如果 .net 没有类似的东西,我会感到惊讶。

    【讨论】:

    • 我尽量避免修改构建/运行过程,但是是的,您也可以在 .NET 中阅读命令行选项 :)
    【解决方案3】:

    我知道这是旧的,但提供的解决方案不是很令人满意。

    我改用了以下类:

    using System.IO;
    using System.Reflection;
    
    public static class Program
    {
        public static string ExecutablePath
        {
            get;
            private set;
        }
    
        static Program()
        {
            var assemblyPath = Assembly.GetEntryAssembly().Location;
            var assemblyDirectory = Path.GetDirectoryName(assemblyPath);
    
            if (assemblyDirectory.EndsWith(@"\Debug") || assemblyDirectory.EndsWith(@"\Release"))
            {
                string projectFile = Path.GetFileNameWithoutExtension(assemblyPath) + ".csproj";
    
                var root = new DirectoryInfo(assemblyDirectory);
    
                while (root.Parent != null)
                {
                    if (File.Exists(Path.Combine(root.FullName, projectFile)))
                        break;
    
                    root = root.Parent;
    
                    if (root.Parent == null) // we could not find it (should not happen)
                        ExecutablePath = assemblyDirectory;
                }
    
                ExecutablePath = root.FullName;
            }
            else
            {
                ExecutablePath = assemblyDirectory;
            }
        }
    }
    

    然后你可以使用Program.ExecutablePath。如果您已经有一个名为 Program 的类,您可以通过这些属性和方法对其进行扩展。

    如果从 Visual Studio 运行,它将为您提供 csproj 文件所在的项目路径。这是没有“bin\*\Debug”或“bin\*\Release”的可执行文件路径。

    如果不是从 Visual Studio 运行,它将为您提供可执行文件所在的路径。

    该解决方案独立于调试设置、其他附加的调试器或构建配置。唯一重要的是,您的配置被命名为“Release”和“Debug”。

    注意:正如 Troy Gizzi 在 cmets 中提到的,此解决方案仅在您从输出目录以外的其他目录运行可执行文件时才有效。对于我的用例(以项目目录为根目录模拟部署目录结构),这是一个合适的解决方案。一般来说,我稍后将我的可执行文件复制到部署目录,并期望与我在 Visual Studio 中运行我的程序的行为相同。在我的例子中,内容和其他依赖项相对于项目目录。

    【讨论】:

    • 这种方法对我不起作用。无论我是从 VS 启动它,还是从 CLI 启动它,它仍然显示相同的路径(项目目录)。
    • 您的配置名称是什么,项目配置中的输出目录是什么?也许您可以启动调试器来查看它为什么不工作。我的猜测是您的输出目录不会以“Debug”和/或“Release”结尾。在这种情况下,您可能希望使用 Contains 而不是 EndsWith。
    • 我只是使用默认的 Debug & Release 配置,并带有匹配的“Debug”和“Release”输出目录名称。
    • 我认为这个解决方案假定“在 Visual Studio 之外运行”也意味着“在输出路径之外运行”。在我的例子中,我直接从输出路径运行可执行文件,所以路径与我在 VS 中运行它时的路径相同。
    • 是的,这是真的。该解决方案用于区分“在开发时运行”和“在指定位置运行(例如发布时)”。在我的例子中,我的开发目录结构有一个形式,其中项目目录用作根目录,它等于已发布产品中的根目录。因此,我的主程序集访问相对于根目录的数据,根目录是项目目录而不是输出目录。我想这是一个常见的用例。我的解决方案正是为这个用例设计的。
    【解决方案4】:

    你考虑过命令行参数吗?使用 --no-exception-handling 标志(或任何听起来合适的标志)从 Visual Studio 运行程序,如果传入该参数,则不处理异常。当您在其他地方启动程序时,如果没有此参数,它将表现正常。

    【讨论】:

      【解决方案5】:

      我将添加一个启用报告功能的配置标志,而不是按流程树进行跟踪。除非您在 DEV 环境中,否则该标志始终默认为“true”,然后将其设置为“false”。

      【讨论】:

        【解决方案6】:

        有时应用程序是在调试器之外启动的,调试器稍后会被附加。 (双击应用程序分配到的文件...)我使用此代码等待调试器附加。

        using System.Diagnostics;
        
        Process[] procName = Process.GetProcessesByName("devenv");
        
        if(procName.Length > 0)
          MessageBox.Show("Wait for debugger attach");
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-05
          • 1970-01-01
          • 2018-05-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-20
          • 2016-07-25
          相关资源
          最近更新 更多