이 글은 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'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'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 중국어 웹사이트의 기타 관련 기사를 참조하세요!