ホームページ  >  記事  >  バックエンド開発  >  C# でのプロセスの一時停止と回復のコード例分析 (写真)

C# でのプロセスの一時停止と回復のコード例分析 (写真)

黄舟
黄舟オリジナル
2017-03-27 10:59:272132ブラウズ

この記事は主に 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. 効果画像:

は例であり、2 つの画像が作成されます。1 つは子プロセスを表示するもので、もう 1 つは子プロセスを非表示にするものです。

実際のプロジェクトは、図に示すように、独立したプロセス モジュールを隠れた方法で呼び出し、ホストを使用してその処理の進行状況を表示します。

追記:

アイデアを拡張youtube_dl、ffmpeg などの優れたオープンソース ツールはすべて独立したプロセスとして存在し、CMD を通じて通信を管理できます。

このプロセス制御原理を使用すると、これらのオープンソース ツールに基づいて非常に優れた GUI ツールを作成できます。結局のところ、強力なコマンドラインに比べて、人々は依然として単純な操作を便利だと考えています。

以上がC# でのプロセスの一時停止と回復のコード例分析 (写真)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。