C#-将进程注册为子进程,父进程崩溃的时候子进程也随之退出的方案和实例

Kill child process when parent process is killed

我正在使用我的应用程序中的System.Diagnostics.Process类创建新进程。

当/如果我的应用程序崩溃了,我希望这个进程被杀死。 但是如果我从任务管理器中删除我的应用程序,子进程就不会被杀死。 有没有办法让子进程依赖于父进程?

如果关闭强制关闭父进程,Process类启动的子进程就会被提升为独立的进程,能不能让子进程随着父进程的崩溃而一起退出呢?当然是有的,通过windows自带的作业对象来完成

本文来自机翻问答:关于c#:杀死父进程时杀死子进程

首先作业对象的使用需要用到枚举类型如下:

 public enum JobObjectInfoType
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11
} [StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
} [StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public Int16 LimitFlags;
public UInt32 MinimumWorkingSetSize;
public UInt32 MaximumWorkingSetSize;
public Int16 ActiveProcessLimit;
public Int64 Affinity;
public Int16 PriorityClass;
public Int16 SchedulingClass;
} [StructLayout(LayoutKind.Sequential)]
struct IO_COUNTERS
{
public UInt64 ReadOperationCount;
public UInt64 WriteOperationCount;
public UInt64 OtherOperationCount;
public UInt64 ReadTransferCount;
public UInt64 WriteTransferCount;
public UInt64 OtherTransferCount;
} [StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public UInt32 ProcessMemoryLimit;
public UInt32 JobMemoryLimit;
public UInt32 PeakProcessMemoryUsed;
public UInt32 PeakJobMemoryUsed;
}

引用系统接口如下:

    /// <summary>
/// 创建作业对象
/// </summary>
/// <param name="lpJobAttributes">该作业的安全描述符</param>
/// <param name="name">作业名字</param>
/// <returns></returns>
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string name); /// <summary>
/// 将进程注册为作业对象进程
/// </summary>
/// <param name="job">作业对象句柄</param>
/// <param name="process">进程句柄</param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); /// <summary>
/// 设置作业对象限制
/// </summary>
/// <param name="hJob">标识要限制的作业 </param>
/// <param name="infoType">枚举类型,用于指明要使用的限制类型</param>
/// <param name="lpJobObjectInfo">包含限制设置值的数据结构的地址</param>
/// <param name="cbJobObjectInfoLength">指明第三个参数的大小</param>
/// <returns></returns>
[DllImport("kernel32.dll")]
static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);

我们所有的工作就是围绕上面这三个接口来展开,我在这里写一个类叫JobControl类,具体调用示例代码如下

   Process target_process = new Process();

  JobControl clsJobControl = new JobControl();

   clsJobControl.AddProcess(target_process);

到这这个进程就被注册为主进程的子进程了,具体的JobControl类的内容如下,主要看构造函数和AddMessage即可

        using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks; namespace LBD.CloudNetIntelClassroom.Seat
{
public class JobControl
{
public enum JobObjectInfoType
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11
} [StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
} [StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public Int16 LimitFlags;
public UInt32 MinimumWorkingSetSize;
public UInt32 MaximumWorkingSetSize;
public Int16 ActiveProcessLimit;
public Int64 Affinity;
public Int16 PriorityClass;
public Int16 SchedulingClass;
} [StructLayout(LayoutKind.Sequential)]
struct IO_COUNTERS
{
public UInt64 ReadOperationCount;
public UInt64 WriteOperationCount;
public UInt64 OtherOperationCount;
public UInt64 ReadTransferCount;
public UInt64 WriteTransferCount;
public UInt64 OtherTransferCount;
} [StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public UInt32 ProcessMemoryLimit;
public UInt32 JobMemoryLimit;
public UInt32 PeakProcessMemoryUsed;
public UInt32 PeakJobMemoryUsed;
} /// <summary>
/// 创建作业对象
/// </summary>
/// <param name="lpJobAttributes">该作业的安全描述符</param>
/// <param name="name">作业名字</param>
/// <returns></returns>
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string name); /// <summary>
/// 将进程注册为作业对象进程
/// </summary>
/// <param name="job">作业对象句柄</param>
/// <param name="process">进程句柄</param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); /// <summary>
/// 设置作业对象限制
/// </summary>
/// <param name="hJob">标识要限制的作业 </param>
/// <param name="infoType">枚举类型,用于指明要使用的限制类型</param>
/// <param name="lpJobObjectInfo">包含限制设置值的数据结构的地址</param>
/// <param name="cbJobObjectInfoLength">指明第三个参数的大小</param>
/// <returns></returns>
[DllImport("kernel32.dll")]
static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);
const System.String job_name = "Leventure_SeatJob";
private System.UInt32 job_ptr = 0;
private System.IntPtr job_handle = System.IntPtr.Zero;
/// <summary>
/// 构造函数,声明作业对象,限制作业对象。
/// </summary>
public JobControl()
{
job_handle = CreateJobObject(System.IntPtr.Zero, job_name);
JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
info.LimitFlags = 0x2000;
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
extendedInfo.BasicLimitInformation = info;
//Design by LeventureQys
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!SetInformationJobObject(job_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error()));
} /// <summary>
/// 为该dll注册子进程,当主程序崩溃的时候,子进程一样退出
/// </summary>
/// <param name="added_process"></param>
/// <returns></returns>
public bool AddProcess(Process added_process)
{
System.IntPtr handle = System.IntPtr.Zero;
handle = added_process.Handle;
return AssignProcessToJobObject(job_handle, handle);
}
}
}

C#-将进程注册为子进程,父进程崩溃的时候子进程也随之退出的方案和实例的更多相关文章

  1. Windows批处理 调用程序后 不等待子进程 父进程继续执行命令

    从DOS过来的老鸟应该都知道批处理,这个功能在WINDOWS中仍然保留着.批处理 说白了就是把一系列DOS命令写在一个文本文件里,然后把这个文件命名为XXX.bat(WINXP以后的系统也可以命名为* ...

  2. 2020-04-17:说说redis的rdb原理。假设服务器的内存8g,redis父进程占用了6g,子进程fork父进程后,子父进程总共占用内存12g,如何解决内存不足的问题?(挖)

    福哥答案2020-04-18: 这是一道挖坑题.内存占用只会比6g多一点,不会用12g.fork+cow.

  3. 父进程等待子进程结束 waitpid wait

    我们一直在强调一个概念就是进程是一个程序执行的实例,是内核在虚拟概念下创建的实体,它实例化的体现在用户态就是程序代码和代码使用的变量(存储空间),在内核态就是内核为我们每个进程所保存的数据结构(状态信 ...

  4. fork出的子进程和父进程的继承关系【转载】

    [原文地址]http://blog.163.com/dengjingniurou@126/blog/static/53989196200962924412524/ fork出的子进程和父进程的继承关系 ...

  5. linux的fork()函数具体解释 子进程复制父进程什么

    #include<stdio.h>   #include<string.h>   #include<stdlib.h>   #include<unistd.h ...

  6. PHP多进程学习(三)__代码案例来了解父进程与子进程的执行顺序

    pcntl_fork创建子进程成功的话,系统就有了2个进程,一个为父进程,一个为子进程,父进程和子进程都继续向下执行,子进程的id号为$pid(父进程会获取子进程的$pid也就是$pid不为0,而子进 ...

  7. Linux内核学习笔记(2)-- 父进程和子进程及它们的访问方法

    Linux系统中,进程之间有一个明显的继承关系,所有进程都是 PID 为1的 init 进程的后代.内核在系统启动的最后阶段启动 init 进程.该进程读取系统的初始化脚本(initscript)并执 ...

  8. fork之后,子进程从父进程那继承了什么(转载)

    转载自:https://blog.csdn.net/xiaojun111111/article/details/51764389 知道子进程自父进程继承什么或未继承什么将有助于我们.下面这个名单会因为 ...

  9. 关于父进程和子进程的关系(UAC 绕过思路)

    表面上看.在windows中. 假设是a进程创建了b进程,那么a进程就是b进程的父进程.反之,假设是b创建了a,那么b进程就是a的父进程,这是在windows出现以来一直是程序员们都证实的,可是在在w ...

  10. linux 线程的内核栈是独立的还是共享父进程的?

    需要考证 考证结果: 其内核栈是独立的 206 static struct task_struct *dup_task_struct(struct task_struct *orig) 207 { 2 ...

随机推荐

  1. Elastic:Elastic Maps 基于位置的警报 - 7.10

    文章转载自:https://elasticstack.blog.csdn.net/article/details/112535618

  2. 从dva到vuex的使用方法()

    官网文档:https://vuex.vuejs.org/zh/ 辅助理解的博客:https://blog.csdn.net/m0_70477767/article/details/125155540 ...

  3. 工厂有了 ERP 系统,为什么还要上 MES 系统?

    工厂可以没有ERP,但如果要用系统,必定是MES系统!所以即使工厂有了ERP,也还是要上MES系统的.产生这样的疑问很重要的一个原因是没有明确ERP与MES到底是啥.ERP是Enterprise Re ...

  4. Java之POI导出Excel(一):单sheet

    相信在大部分的web项目中都会有导出导入Excel的需求,今天我们就来看看如何用Java代码去实现 用POI导出Excel表格. 一.pom引用 pom文件中,添加以下依赖 查看代码  <!-- ...

  5. P7113 [NOIP2020] 排水系统 (拓扑排序)

    (不想打高精,也不想学习其他大佬的神仙写法,打了90分的错解). 本题容易想到用拓扑排序处理,涉及分数的加法,用long long会超时,不过通分时先除后乘卡一下也可以拿90分. 结构体真是个复杂的东 ...

  6. Mysql编程中遇到的小错误

    我在mysql中创建的数据库表语句为如下 create table grade (id int not null, name varchar(255), desc varchar(255), prim ...

  7. Linux自动切换用户

    Linux自动切换用户 一.创建sh文件 touch su_user.sh 二.下载脚本 yum install -y expect 三.脚本内容 #!/bin/bash# This is our f ...

  8. Vue学习之--------监视属性(2022/7/10)

    文章目录 1.监视属性 1.1 监视属性--天气案例 1.1.1 基础知识 1.1.2 代码实例 1.1.2 测试效果 1.2 深度监视-天气案例 1.2.1 基础知识 1.2.2 代码实例 1.2. ...

  9. 齐博x1 APP要实现直播的关键两步

    大家务必要注意,缺少这两步,你的APP将不能实现直播, 也即点击直播按钮无法启动直播推流

  10. flutter系列之:flutter中可以建索引的栈布局IndexedStack

    目录 简介 IndexedStack简介 IndexedStack的使用 总结 简介 之前我们介绍了一个flutter的栈结构的layout组件叫做Stack,通过Stack我们可以将一些widget ...