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. C语言指针笔记01

    int num = 90; 定义一个整型变量num int* ptr = &num; 定义一个整型指针变量ptr,指针变量ptr的类型取决于他所需要指向的变量,如这里,ptr要指向int类型变 ...

  2. 密码学奇妙之旅、03 HMAC单向散列消息认证码、Golang代码

    HMAC 单向散列消息认证码 消息认证码MAC是用于确认完整性并进行认证的技术,消息认证码的输入包括任意长度的消息和一个发送者和接收者之间共享的密钥(可能还需要共享盐值). HMAC是使用单向散列函数 ...

  3. 我的 Kafka 旅程 - 性能调优

    Producer 于 config/producer.properties 配置文件中的项 # 序列化数据压缩方式 [none/gzip/snappy/lz4/zstd] compression.ty ...

  4. 【博学谷学习记录】超强总结,用心分享|MySql连接查询超详细总结

    一.概述 在实际开发中,大部分情况下都不是在单表中进行数据操作,一般都是多张表进行联合查询.通常一个业务就会对应的有好几张表.MySql中的连接查询分为交叉连接,内连接,外连接三部分.其中交叉连接也叫 ...

  5. Podman容器技术基础

    Podman容器技术基础 目录 Podman容器技术基础 简介 安装 基础命令 简介 Podman 是一个开源的容器运行时项目,可在大多数 Linux 平台上使用.Podman 提供与 Docker ...

  6. 大数据技术之HBase原理与实战归纳分享-下

    @ 目录 整合Phoenix 定义 为何要使用 安装 SHELL操作 表的映射 简易JDBC示例 二级索引 二级索引配置文件 全局索引 包含索引 本地索引(local index) HBase与 Hi ...

  7. Linux 下搭建 Hadoop 环境

    Linux 下搭建 Hadoop 环境 作者:Grey 原文地址: 博客园:Linux 下搭建 Hadoop 环境 CSDN:Linux 下搭建 Hadoop 环境 环境要求 操作系统:CentOS ...

  8. grpc错误处理

    0.1.索引 https://waterflow.link/articles/1665938704477 我们都知道当发起http请求的时候,服务端会返回一些http状态码,不管是成功还是失败.客户端 ...

  9. 虚拟机里网络连接的几种方式说明(桥接,NAT, 仅主机)

    虚拟机里网络连接类型的选择: 桥接:选择桥接模式的话虚拟机和宿主机在网络上就是平级的关系,相当于连接在同一交换机上. NAT:NAT模式就是虚拟机要联网得先通过宿主机才能和外面进行通信. 仅主机:虚拟 ...

  10. 二十六、StatefulSet资源控制器

    StatefulSet资源控制器 一.statefulset介绍 StatefulSet 是为了解决有状态服务的问题而设计的资源控制器. 匹配 Pod name ( 网络标识 ) 的模式为:(stat ...