【问题标题】:See if other assembly is being debugged查看是否正在调试其他程序集
【发布时间】:2012-08-07 14:20:54
【问题描述】:

我们有一个程序集,我们称之为Foo.exe。此可执行文件将由另一个应用程序启动,例如 Bar1.exeBar2.exe

如果Foo.exe 运行,它每10 秒检查一次Bar1Bar2 进程是否正在运行。如果没有,它会清理一些东西并关闭。

这适用于普通用户场景。但是如果我们开发,我们会遇到一个大问题: 应用程序无法查看应用程序Bar1Bar2 是否处于调试状态,在这两种情况下Bar.svhost.exe 都在任务管理器中可用。

也就是说,如果Bar.svhost.exe会被忽略,Foo.exe会在调试过程中结束,这是不可能的。

但是如果Bar.svhost.exe 会被看到,Foo.exe 永远不会结束,我们必须手动杀死它,但它没有被正确清理。

知道如何解决这个问题吗?

(在Bar1Bar2 中结束Foo.exe 是不可能的,因为可以在机器上运行多个Bar1Bar2Foo 只需运行一次。因此@ 987654341@ 必须检查自己。“杀死”进程将让它清理)

添加: 这里是问题的伪代码示例

//Bar1.exe and Bar2.exe
void Main()
{
    if (!FooIsRunning())
        StartFoo();
    DoSomething();
}

//Foo.exe
void Main()
{
    Initialize();
    while (BarIsRunning());
    Cleanup();
}

private bool BarIsRunning()
{
    var processes = Process.GetProcesses();
    if (processes.Any(p => p.ProcessName.Contains("Bar.exe"))
        return true;

    var vshostProcess = processes.FirstOrDefault(p => p.ProcessName.Contains("Bar.vshost.exe");
    return vshostProcess != null && ProcessIsDebugging(process);
}

private bool ProcessIsDebugging(Process process)
{
    // How to...
    return true;
}

【问题讨论】:

  • 您是否特别想知道它是否正在被调试,或者您是否只需要解决“Foo 应该在Bar1Bar2 的最后一个实例退出后退出(其中多个实例可能会运行)”?
  • Out of Foo 我需要知道 Bar1 或 Bar2 是否在调试器中运行。换句话说,Foo 必须知道是否存在任何 Bar1 或 Bar2 的实例。
  • 您专注于调试方面 - 但我仍然不确定这是否至关重要,或者只是您提出的一个示例,其中一种更简单的技术不起作用(我不知道) '不知道您是否考虑了具有相同可执行名称的外国Bar1 程序)
  • 我专注于调试方面,因为只有这一次场景是有问题的。在客户机器上运行时,一切运行良好。但我们也希望在调试会话之外彻底关闭。我们的第一个想法是让 Bar 告诉 Foo “请关闭”,但是没有像 WCF 这样的特殊通信方式,我们没有干净的方式,因此我们说 Foo 必须关心自己。

标签: c# visual-studio process


【解决方案1】:

你检查过Debugger.IsAttached吗?

【讨论】:

  • 看起来很有趣。如果在 Foo 中我有 Process Bar1,我可以检查 Bar1 是否连接到调试器吗? Foo 本身永远不会被调试
  • Foe 例子,Foo 确实喜欢这个 void Main() { if (IsBarRunning()) ShutDown(); } private static bool IsBarRunning() { return Process.GetProcesses().Any(p => p.ProcessName.Contains("Bar")); }
  • 调试器附加到一个进程。在该进程的上下文中、在任何程序集中、在任何线程中执行的任何代码都应该看到与 Debugger.IsAttached 相同的值。
  • 是的,但如果我没看错,我只能直接在 Bar1.exe 或 Bar2.exe 的代码中检查 Debugger.IsAttached。从这方面我无法处理这个问题,因为在 Bar 之外我无法正确关闭 Foo。因此 Foo 必须检查 Bar 是否正在被调试。我需要barProcess.IsDebugging
【解决方案2】:

如果您想检查其他应用程序是否附加了调试器,请使用CheckRemoteDebuggerPresent

我已经为进程编写了一个扩展方法:

public static class ProcessExtensions
{
    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
    static extern bool CheckRemoteDebuggerPresent(IntPtr hProcess, ref bool isDebuggerPresent);

    public static bool IsDebuggerAttached(this Process process)
    {
        try
        {
            var isDebuggerAttached = false;
            CheckRemoteDebuggerPresent(process.Handle, ref isDebuggerAttached);

            return isDebuggerAttached;
        }
        catch (Exception)
        {
            return false;
        }
    }
}

【讨论】:

    【解决方案3】:

    我想我解决了这个问题。我发现如果 Bar1 或 Bar2 将被调试,MainWindowTitle 是不同的。 直到调试 Bar1.vshost.exe 的 MainWindowTitle 才是真正的应用程序标题,否则 MainWindowTitle 为空。

    Foo.exe

    private static bool IsLastClientClosed()
    {
        var processes = Process.GetProcesses();
    
        var debuggingProcesses = processes.Where(p => p.ProcessName.Contains("Bar1.vshost") || p.ProcessName.Contains("Bar2.vshost")).ToList();
        if (debuggingProcesses.Any())
            return !DebuggingRuns(debuggingProcesses);
    
        return processes.Any(p => p.ProcessName.StartsWith("Bar1") || p.ProcessName.StartsWith("Bar2"));
    }
    
    private static bool DebuggingRuns(IEnumerable<Process> processes)
    {
        foreach (var process in processes)
        {
            try
            {
                if (!string.IsNullOrEmpty(process.MainWindowTitle))
                    return true;
            }
            catch
            {
            }
        }
        return false;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-01
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多