Files
blackbird/lci/extra/dashun/dashun/Pls.hpp
T
2026-08-02 20:15:07 +08:00

159 lines
3.3 KiB
C++

/* 进程(Process)是计算机中正在执行的程序的一个实例,是
* 操作系统进行资源分配和调度的基本单位
*
* 你可以将其理解为程序的一次动态执行过程——程序
* 是静态的代码文件,而进程是程序运行时的动态实体。
*/
#pragma once
#ifdef _WIN32
#include <WinSock2.h>
#include <Windows.h>
#endif
#include <boost/process/process.hpp>
#include <boost/process/environment.hpp>
#include <boost/asio/io_context.hpp>
#include <list>
#include <memory>
#include <iostream>
namespace qing {
/* 进程列表类,这个类封装了一个
* 容纳Pls::subp的列表
*
* 以及基本的进程操作
*/
class Pls {
public:
// 命名子进程
struct subp {
std::unique_ptr<boost::process::process> p;
std::string name;
};
/* 创建子进程执行一个命令,并且
* 添加到进程列表。
*
* 接受一个std::string类型的文件路径,以及
* std::vector<std::string> 类型的参数列表(缺省)
*
* 优化方案:返回错误信息
*/
void exec(const std::string& path, const std::vector<std::string> &args)
try {
// 检查文件是否存在(好像不会在环境变量中寻找)
if (!boost::filesystem::exists(path)) {
std::cerr << "Error: File not found - " << path << std::endl;
return;
}
// 输入输出上下文
boost::asio::io_context io_ctx;
// 继承当前进程的所有环境变量(旧版)
//auto env = boost::process::environment::current;
// 错误码
boost::system::error_code ec;
// 构造子进程
subp p = { std::move(std::make_unique<boost::process::process>( io_ctx, path, args/*, env, ec*/)), mergeCmd(path, args)};
if (ec) {
std::cerr << "Failed to start process: " << ec.message() << std::endl;
return ;
}
else {
// 推入向量
vec.push_back(std::move(p));
}
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
/* 序列化进程列表 */
inline std::string initialize() {
std::string ret{ "" };
for (auto& item : vec) {
std::ostringstream oss;
ret += (ret == "") ? "" : "\n";
#ifdef _WIN32
DWORD pid = GetProcessId(item.p->native_handle());
oss << pid;
#else
oss << item.p->native_handle();
#endif
ret += oss.str();
ret += "\t";
ret += (item.p->running()) ? "Alive" : "Dead";
ret += "\t";
ret += item.name;
}
return ret;
}
// 杀死一个进程
[[noreturn]] void kill(int pid)
try {
for (auto it = vec.begin(); it != vec.end(); ++it)
if ((*it).p->id() == pid && (*it).p->running()) {
(*it).p->terminate();
//(*it).p->wait(); // 可能杀不死?
//vec.erase(it); // 清除
break;
}
}
catch (std::exception &ex) {
std::cout << ex.what() << std::endl;
}
// 清理死掉的进程
[[noreturn]] void clear() {
for (auto it = vec.begin(); it != vec.end();)
if (!(*it).p->running()) {
it = vec.erase(it);
}
else {
++it;
}
}
// 关闭所有进程
[[noreturn]] void closeAll() {
for (auto& item : vec)
if (item.p->running())
item.p->terminate();
// 加上这个似乎更清爽一些
clear();
}
private:
// 容纳子进程的链表
std::list<subp> vec{};
// 用于操作链表的锁
//std::mutex mtx{};
/* 将一个启动脚本地址,和一个
* 字符串向量组成的参数列表,组装
* 成一条完整的启动命令
*/
inline static std::string mergeCmd(const std::string& path, const std::vector<std::string>& args) {
std::string ret = path;
for (const auto& item : args) {
ret += " ";
ret += item;
}
return ret;
}
};
}