我们有一个程序集,我们称之为Foo.exe
。此可执行文件将由另一个应用程序启动,例如 Bar1.exe
或 Bar2.exe
.
如果Foo.exe
运行,它会每 10 秒检查一次Bar1
或Bar2
进程是否正在运行。如果没有,它会清理一些东西并关闭。
这适用于普通用户方案。但是如果我们开发,我们有一个大问题:应用程序无法查看应用程序Bar1
或Bar2
是否正在调试中,在这两种情况下,Bar.svhost.exe
在任务管理器中都可用。
这意味着,如果Bar.svhost.exe
将被忽略,Foo.exe
调试过程中结束,这是不可能的。
但是如果看到Bar.svhost.exe
,Foo.exe
永远不会结束,我们必须手动杀死,但后来它没有被正确清洁。
知道如何解决问题吗?
(无法在Bar1
或Bar2
中结束Foo.exe
,因为可以在计算机上运行多个Bar1
或Bar2
,但Foo
只需要运行一次。因此,Foo.exe
必须自我检查。并且"杀死"过程将让它清理)
加:这里有一个伪代码问题的例子
//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;
}
你检查过 Debugger.IsAttached 吗?
检查其他应用程序是否附加了调试器,请使用 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;
}
}
}
我解决了这个问题。我发现如果 Bar1 或 Bar2 将被调试,MainWindowTitle 是不同的。在调试之前,Bar1.vshost的MainWindowTitle.exe将是真正的应用程序标题,如果不是,则MainWindowTitle为空。
福.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;
}