>  기사  >  백엔드 개발  >  C#에서 프로세스 중단 및 복구에 대한 코드 예제 분석(그림)

C#에서 프로세스 중단 및 복구에 대한 코드 예제 분석(그림)

黄舟
黄舟원래의
2017-03-27 10:59:272088검색

이 글은 C#에서 프로세스를 일시 중지하고 재개하는 방법을 주로 소개합니다. 매우 좋고 참고할 가치가 있습니다.

1. 유래:

는 여전히 모듈화프로그래밍에 따른 수요입니다. 제품 관리자는 서비스하기 어렵고 여성 제품 관리자는 더 어렵습니다 ~:p

이건 순전히 농담입니다. 기술 솔루션은 제품 관리자와 관련이 없습니다. 타로를 비난하지 마십시오!

VCU10 프로젝트 재구성에서는 각 기능 모듈을 독립적인 프로세스로 구현해야 합니다. 예를 들어 오디오 및 비디오 변환 모듈이 독립적인 프로세스로 구현되는 경우 일시 중지, 계속 및 기타 기능을 어떻게 제어할 수 있습니까?

스레드는 일시 중지 및 재개가 가능하지만 C#에 내장된 프로세스에는 이러한 메서드가 없습니다. 어떻게 해야 합니까?

산과 강은 지치고 빠져나갈 길은 없지만, 검은 버드나무와 화사한 꽃이 피어나는 또 다른 마을이 있습니다. 사랑이 강해지면 선명해지고 약해집니다. 이 사랑은 기억 속에 기억될 수 있습니다!

이전 기사에서는 프로세스 간 데이터 전송 방법을 설명했으며, 이번 기사에서도 예제를 사용하여 제어 및 데이터 상호 작용 방법을 보여줍니다.

2. 미공개 API 함수: NtSuspendProcess, NtResumeProcess

이러한 함수는 MSDN에서 찾을 수 없습니다.

그 이유는 Windows API와 커널 API 사이에 있고 그 위력을 과소평가할 수 없기 때문입니다. 28 Rakes의 프로그래머들이 이를 악용하여 문제를 일으킬까 두려워서 몰래 숨겨두었습니다.

실제로 NtTerminateProcess도 있습니다. Process에는 Kill 메소드가 있으므로 필요하지 않습니다.

그러나 아무리 비밀스러운 것도 가치가 있는 한 남들이 파헤쳐 주기 마련입니다. 좋은 와인은 깊은 골목도 두렵지 않습니다!

이를 바탕으로 모듈형 프로그래밍에서 프로세스 간 제어의 필요성을 실현할 수 있는 프로세스 관리 클래스를 설계해 보세요.

3. ProcessMgr

코드로 바로 가서 프로세스 관리 유닛을 캡슐화해 보겠습니다.

public static class ProcessMgr
 {
  /// <summary>
  /// The process-specific access rights.
  /// </summary>
  [Flags]
  public enum ProcessAccess : uint
  {
   /// <summary>
   /// Required to terminate a process using TerminateProcess.
   /// </summary>
   Terminate = 0x1,
   /// <summary>
   /// Required to create a thread.
   /// </summary>
   CreateThread = 0x2,
   /// <summary>
   /// Undocumented.
   /// </summary>
   SetSessionId = 0x4,
   /// <summary>
   /// Required to perform an operation on the address space of a process (see VirtualProtectEx and WriteProcessMemory).
   /// </summary>
   VmOperation = 0x8,
   /// <summary>
   /// Required to read memory in a process using ReadProcessMemory.
   /// </summary>
   VmRead = 0x10,
   /// <summary>
   /// Required to write to memory in a process using WriteProcessMemory.
   /// </summary>
   VmWrite = 0x20,
   /// <summary>
   /// Required to duplicate a handle using DuplicateHandle.
   /// </summary>
   DupHandle = 0x40,
   /// <summary>
   /// Required to create a process.
   /// </summary>
   CreateProcess = 0x80,
   /// <summary>
   /// Required to set memory limits using SetProcessWorkingSetSize.
   /// </summary>
   SetQuota = 0x100,
   /// <summary>
   /// Required to set certain information about a process, such as its priority class (see SetPriorityClass).
   /// </summary>
   SetInformation = 0x200,
   /// <summary>
   /// Required to retrieve certain information about a process, such as its token, exit code, and 
   priority class (see OpenProcessToken, GetExitCodeProcess, GetPriorityClass, and IsProcessInJob).
   /// </summary>
   QueryInformation = 0x400,
   /// <summary>
   /// Undocumented.
   /// </summary>
   SetPort = 0x800,
   /// <summary>
   /// Required to suspend or resume a process.
   /// </summary>
   SuspendResume = 0x800,
   /// <summary>
   /// Required to retrieve certain information about a process (see QueryFullProcessImageName). 
   A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION.
   /// </summary>
   QueryLimitedInformation = 0x1000,
   /// <summary>
   /// Required to wait for the process to terminate using the wait functions.
   /// </summary>
   Synchronize = 0x100000
  }
  [DllImport("ntdll.dll")]
  private static extern uint NtResumeProcess([In] IntPtr processHandle);
  [DllImport("ntdll.dll")]
  private static extern uint NtSuspendProcess([In] IntPtr processHandle);
  [DllImport("kernel32.dll", SetLastError = true)]
  private static extern IntPtr OpenProcess(
   ProcessAccess desiredAccess,
   bool inheritHandle,
   int processId);
  [DllImport("kernel32.dll", SetLastError = true)]
  [return: MarshalAs(UnmanagedType.Bool)]
  private static extern bool CloseHandle([In] IntPtr handle);
  public static void SuspendProcess(int processId)
  {
   IntPtr hProc = IntPtr.Zero;
   try
   {
    // Gets the handle to the Process
    hProc = OpenProcess(ProcessAccess.SuspendResume, false, processId);
    if (hProc != IntPtr.Zero)
     NtSuspendProcess(hProc);
   }
   finally
   {
    // Don&#39;t forget to close handle you created.
    if (hProc != IntPtr.Zero)
     CloseHandle(hProc);
   }
  }
  public static void ResumeProcess(int processId)
  {
   IntPtr hProc = IntPtr.Zero;
   try
   {
    // Gets the handle to the Process
    hProc = OpenProcess(ProcessAccess.SuspendResume, false, processId);
    if (hProc != IntPtr.Zero)
     NtResumeProcess(hProc);
   }
   finally
   {
    // Don&#39;t forget to close handle you created.
    if (hProc != IntPtr.Zero)
     CloseHandle(hProc);
   }
  }
 }

4. 프로세스 제어

호스트로 메인 프로세스가 있으며, Process 클래스를 통해 하위 프로세스를 호출하고 사용할 ID를 얻습니다. 호출 코드는

 private void RunTestProcess(bool hidden = false)
  {
   string appPath = Path.GetDirectoryName(Application.ExecutablePath);
   string testAppPath = Path.Combine(appPath, "TestApp.exe");
   var pi = new ProcessStartInfo();
   pi.FileName = testAppPath;
   pi.Arguments = this.Handle.ToString();
   pi.WindowStyle = hidden ? ProcessWindowStyle.Hidden : ProcessWindowStyle.Normal;
   this.childProcess = Process.Start(pi);
   txtInfo.Text = string.Format("子进程ID:{0}\r\n子进程名:{1}", childProcess.Id, childProcess.ProcessName);
   ...
  }

제어 코드는

private void btnWork_Click(object sender, EventArgs e)
  {
   if (this.childProcess == null || this.childProcess.HasExited)
    return;
   if ((int)btnWork.Tag == 0)
   {
    btnWork.Tag = 1;
    btnWork.Text = "恢复";
    ProcessMgr.SuspendProcess(this.childProcess.Id);
   }
   else
   {
    btnWork.Tag = 0;
    btnWork.Text = "挂起";
    ProcessMgr.ResumeProcess(this.childProcess.Id);
   }
  }

하위 프로세스는 타이머를 사용하여 작업을 시뮬레이션하고 기본 프로세스에 진행 메시지를 보냅니다. 🎜>

 private void timer_Tick(object sender, EventArgs e)
  {
   if (progressBar.Value < progressBar.Maximum)
    progressBar.Value += 1;
   else
    progressBar.Value = 0;
   if (this.hostHandle != IntPtr.Zero)
    SendMessage(this.hostHandle, WM_PROGRESS, 0, progressBar.Value);
  }

코드량이 너무 적어 간단해요...

5. 렌더링:

예시로 , 두 개를 만들었습니다. 그림에서 하나는 자식 프로세스를 나타내고 다른 하나는 자식 프로세스를 나타냅니다.

실제 프로젝트에서는 숨겨진 방식으로 호출되는 독립 프로세스 모듈을 호출하고, 호스트는 그림과 같이 처리 진행 상황을 표시합니다.

추첨:

아이디어를 확장하면 youtube_dl, ffmpeg 등과 같은 일부 우수한 오픈 소스 도구는 독립적인 프로세스로 존재하며 CMD를 통해 통신을 관리합니다.

이 프로세스 제어 원리를 사용하면 이러한 오픈 소스 도구를 기반으로 꽤 좋은 GUI 도구를 만들 수 있습니다. 결국, 강력한 명령줄에 비해 사람들은 여전히 ​​간단한 작업을 편리하다고 생각합니다.

위 내용은 C#에서 프로세스 중단 및 복구에 대한 코드 예제 분석(그림)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.