首页 后端开发 C#.Net教程 C#中进程的挂起与恢复的代码实例分析(图)

C#中进程的挂起与恢复的代码实例分析(图)

Mar 27, 2017 am 10:59 AM

这篇文章主要介绍了C#中进程的挂起与恢复操作方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下

1. 源起:

仍然是模块化编程所引发的需求。产品经理难伺候,女产品经理更甚之~:p

纯属戏谑,技术方案与产品经理无关,芋头莫怪!

VCU10项目重构,要求各功能模块以独立进程方式实现,比如:音视频转换模块,若以独立进程方式实现,如何控制其暂停、继续等功能呢?

线程可以Suspend、Resume,c#内置的Process没有此类方法,咋整?

山穷水尽疑无路,柳暗花明又一村。情到浓时清转薄,此情可待成追忆!

前篇描述了进程间数据传递方法,此篇亦以示例演示其间控制与数据交互方法。

 2、未公开的API函数:NtSuspendProcess、NtResumeProcess

此类函数在MSDN中找不到。

思其原因,概因它们介于Windows API和 内核API之间,威力不容小觑。怕二八耙子程序员滥用而引发事端,因此密藏。

其实还有个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

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

使用 C# 的活动目录 使用 C# 的活动目录 Sep 03, 2024 pm 03:33 PM

使用 C# 的 Active Directory 指南。在这里,我们讨论 Active Directory 在 C# 中的介绍和工作原理以及语法和示例。

C# 中的随机数生成器 C# 中的随机数生成器 Sep 03, 2024 pm 03:34 PM

C# 随机数生成器指南。在这里,我们讨论随机数生成器的工作原理、伪随机数和安全数的概念。

C# 序列化 C# 序列化 Sep 03, 2024 pm 03:30 PM

C# 序列化指南。这里我们分别讨论C#序列化对象的介绍、步骤、工作原理和示例。

C# 数据网格视图 C# 数据网格视图 Sep 03, 2024 pm 03:32 PM

C# 数据网格视图指南。在这里,我们讨论如何从 SQL 数据库或 Excel 文件加载和导出数据网格视图的示例。

C# 中的模式 C# 中的模式 Sep 03, 2024 pm 03:33 PM

C# 模式指南。在这里,我们讨论 C# 中模式的介绍和前 3 种类型,以及其示例和代码实现。

C# 中的质数 C# 中的质数 Sep 03, 2024 pm 03:35 PM

C# 素数指南。这里我们讨论c#中素数的介绍和示例以及代码实现。

C# 中的阶乘 C# 中的阶乘 Sep 03, 2024 pm 03:34 PM

C# 阶乘指南。这里我们讨论 C# 中阶乘的介绍以及不同的示例和代码实现。

c#多线程和异步的区别 c#多线程和异步的区别 Apr 03, 2025 pm 02:57 PM

多线程和异步的区别在于,多线程同时执行多个线程,而异步在不阻塞当前线程的情况下执行操作。多线程用于计算密集型任务,而异步用于用户交互操作。多线程的优势是提高计算性能,异步的优势是不阻塞 UI 线程。选择多线程还是异步取决于任务性质:计算密集型任务使用多线程,与外部资源交互且需要保持 UI 响应的任务使用异步。

See all articles