Приостановить процесс в C # - PullRequest
24 голосов
/ 16 сентября 2008

Как приостановить весь процесс (как в Process Explorer, когда я нажимаю Suspend) в C #.

Я запускаю процесс с помощью Process.Start, и в случае определенного события я хочу приостановить процесс, чтобы иметь возможность провести некоторое исследование его «снимка».

Ответы [ 5 ]

33 голосов
/ 16 сентября 2008

Вот мое предложение:

 [Flags]
    public enum ThreadAccess : int
    {
      TERMINATE = (0x0001),
      SUSPEND_RESUME = (0x0002),
      GET_CONTEXT = (0x0008),
      SET_CONTEXT = (0x0010),
      SET_INFORMATION = (0x0020),
      QUERY_INFORMATION = (0x0040),
      SET_THREAD_TOKEN = (0x0080),
      IMPERSONATE = (0x0100),
      DIRECT_IMPERSONATION = (0x0200)
    }

    [DllImport("kernel32.dll")]
    static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
    [DllImport("kernel32.dll")]
    static extern uint SuspendThread(IntPtr hThread);
    [DllImport("kernel32.dll")]
    static extern int ResumeThread(IntPtr hThread);
    [DllImport("kernel32", CharSet = CharSet.Auto,SetLastError = true)]
    static extern bool CloseHandle(IntPtr handle);


private static void SuspendProcess(int pid)
{
  var process = Process.GetProcessById(pid);

  if (process.ProcessName == string.Empty)
    return;

  foreach (ProcessThread pT in process.Threads)
  {
    IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);

    if (pOpenThread == IntPtr.Zero)
    {
      continue;
    }

    SuspendThread(pOpenThread);

    CloseHandle(pOpenThread);
  }
}

public static void ResumeProcess(int pid)
{
  var process = Process.GetProcessById(pid);

  if (process.ProcessName == string.Empty)
    return;

  foreach (ProcessThread pT in process.Threads)
  {
    IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);

    if (pOpenThread == IntPtr.Zero)
    {
      continue;
    }

    var suspendCount = 0;
    do
    {
      suspendCount = ResumeThread(pOpenThread);
    } while (suspendCount > 0);

    CloseHandle(pOpenThread);
  }
}
11 голосов
/ 28 октября 2012

Благодаря Магнусу

После включения флагов я немного изменил код, чтобы он стал методом расширения в моем проекте. Теперь я мог бы использовать

var process = Process.GetProcessById(param.PId);
process.Suspend();

Вот код для тех, кто может быть заинтересован.

public static class ProcessExtension
{
    [DllImport("kernel32.dll")]
    static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
    [DllImport("kernel32.dll")]
    static extern uint SuspendThread(IntPtr hThread);
    [DllImport("kernel32.dll")]
    static extern int ResumeThread(IntPtr hThread);

    public static void Suspend(this Process process)
    {
        foreach (ProcessThread thread in process.Threads)
        {
            var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id);
            if (pOpenThread == IntPtr.Zero)
            {
                break;
            }
            SuspendThread(pOpenThread);
        }
    }
    public static void Resume(this Process process)
    {
        foreach (ProcessThread thread in process.Threads)
        {
            var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id);
            if (pOpenThread == IntPtr.Zero)
            {
                break;
            }
            ResumeThread(pOpenThread);
        }
    }
}

У меня есть утилита, которую я использую для общего приостановления / уничтожения / вывода списка процессов Полный источник на Git

3 голосов
/ 16 сентября 2008

Подробное решение с использованием Win32 p / invoke, можно найти на CodeProject .

2 голосов
/ 02 июля 2009

Таким образом, на самом деле то, что показывает другой ответ, приостанавливает поток в процессе, нет способа действительно приостановить процесс (т. Е. В одном вызове) ....

Немного другое решение состояло бы в том, чтобы фактически отладить целевой процесс, который вы запускаете, см. блог Майка Сталла для получения некоторых советов, как реализовать это из управляемого контекста.

Если вы внедрите отладчик, вы сможете сканировать память или другие снимки, которые вам нужны.

Однако я хотел бы отметить, что технически, теперь есть способ действительно сделать это. Даже если вы выполняете отладку целевого процесса отладки, другой процесс в вашей системе может внедрить поток, и ему будет предоставлена ​​возможность выполнять код независимо от состояния целевого процесса (даже скажем, если он достигнет точки останова из-за нарушения прав доступа) ), если у вас все потоки приостановлены до сверхвысокого числа приостановок, в настоящее время находятся в точке останова в потоке основного процесса и в любом другом таком предположительно замороженном состоянии, система все еще может внедрить другой поток в этот процесс и выполнить некоторые инструкции. Вы также можете решить проблему изменения или замены всех точек входа, которые ядро ​​ обычно вызывает и т. Д., Но теперь вы вступили в гонку вязкой руки MALWARE;) ...

В любом случае, использование управляемых интерфейсов для отладки кажется «намного проще, чем p / invoke» многих вызовов API-интерфейса, которые плохо подражают тому, что вы, вероятно, действительно хотите делать ... используя API отладки;)

1 голос
/ 16 сентября 2008

См. Эту статью CodeProject для ознакомления с основами win32: http://www.codeproject.com/KB/threads/pausep.aspx. В этом примере кода используется библиотека ToolHelp32 из SDK, поэтому я бы рекомендовал превратить этот пример кода в неуправляемую библиотеку C ++ / CLI с простым интерфейсом как "SuspendProcess (uint processID).

Process.Start вернет вам объект Process, из которого вы можете получить идентификатор процесса, а затем передаст его в вашу новую библиотеку на основе вышеуказанного.

Dave

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...