Добавьте следующий код в консольное приложение:
public static class Extensions {
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
static extern bool TerminateThread(IntPtr hThread, uint dwExitCode);
public static Process GetParentProcess(this Process x) {
return (
from it in (new ManagementObjectSearcher("root\\CIMV2", "select * from Win32_Process")).Get().Cast<ManagementObject>()
where (uint)it["ProcessId"]==x.Id
select Process.GetProcessById((int)(uint)it["ParentProcessId"])
).First();
}
public static IEnumerable<Process> GetChildProcesses(this Process x) {
return (
from it in (new ManagementObjectSearcher("root\\CIMV2", "select * from Win32_Process")).Get().Cast<ManagementObject>()
where (uint)it["ParentProcessId"]==x.Id
select Process.GetProcessById((int)(uint)it["ProcessId"])
);
}
public static void Abort(this ProcessThread x) {
TerminateThread(OpenThread(1, false, (uint)x.Id), 1);
}
}
А затем измените свой код следующим образом:
class Program {
static void Main(String[] args) {
// ... (your code might goes here)
try {
Process.GetCurrentProcess().GetParentProcess().Threads.Cast<ProcessThread>().Single().Abort();
}
catch(InvalidOperationException) {
}
Console.Write("Press ONLY key to continue . . . ");
Console.ReadKey(true);
}
}
Итак, все, что мы ожидаем, уже сделано. Я считаю это обходным решением. Он работает под Windows XP SP3
, и я думаю, что он будет работать и с более новыми операционными системами Windows. В Visual Studio приложения всегда являются порожденными процессами. В более ранней версии Visual C++ 6.0 он порождался средой IDE путем вызова VCSPAWN.EXE
; в Visual Studio 2010 ваше приложение запускается со следующей командной строкой при запуске без отладки:
"%comspec%" /c ""имя файла вашего приложения" и пауза"
Поэтому невозможно достичь цели полностью управляемыми способами; потому что он НЕ находился в домене приложения.
Здесь мы используем управляемый способ WMI
для перечисления процессов и инкапсулируем неуправляемые WINAPI
для завершения ProcessThread
, потому что ProcessThread
обычно не прерывается; он предоставляется как что-то только для чтения.
Как упоминалось выше, приложение было создано с помощью конкретной командной строки; у него будет подпись один поток создает один процесс, поэтому мы использовали метод Single()
для извлечения этого потока и его завершения.
Когда мы запускаем приложение в существующей командной строке, это тот же самый сценарий Запуск без отладки. Кроме того, при Начать отладку процесс приложения создается devenv.exe
. У него много потоков, мы знаем это и не будем прерывать ни один поток, просто подскажите и дождитесь нажатия клавиши. Эта ситуация аналогична запуску приложения двойным щелчком или из контекстного меню. Таким образом, процесс приложения создается системной оболочкой, обычно Explorer.exe
, и он также имеет множество потоков.
На самом деле, если мы можем успешно прервать поток, это означает, что у нас есть права на уничтожение родительского процесса. Но нам НЕ это нужно. Нам просто нужно прервать единственный поток, процесс автоматически завершается системой, когда у него больше нет потоков. Убить родительский процесс, определив, что вызывающий процесс — %comspec%
, — еще один способ сделать то же самое, но это опасная процедура. Поскольку процесс, порождающий приложение, может иметь другие потоки, которые имеют любое количество потоков, создают процесс, соответствующий %comspec%
. Вы можете убить критическую работу процесса по небрежности или просто усложнить проверку того, безопасно ли убивать процесс. Поэтому я считаю, что один поток создает один процесс как сигнатуру нашего родительского процесса, который можно безопасно убить/прервать.
WMI
является современным, некоторые из WINAPI
могут стать устаревшими в будущем. Но настоящая причина этой композиции в ее простоте. Старое Tool Help Library
такое же сложное, как и способы преобразования ProcessThread
в System.Threading.Thread
. С помощью LINQ и методов расширения мы можем сделать код более простым и семантическим.
person
Ken Kin
schedule
28.02.2013