Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

node-process-watcher

Package Overview
Dependencies
Maintainers
1
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-process-watcher - npm Package Compare versions

Comparing version
1.6.3
to
1.6.5
+130
lib/index.d.ts
export interface process_info {
id: number;
name: string;
user_name: string;
mem: number;
cpu: number;
}
export interface node_process_watcher_type {
/**
* 监听进程,需要提供一个 key
* @param key
* @param call
* @param pids 监听特定进程信息(只是起到过滤作用)
*/
on: (key: string, call: (list: process_info[]) => any, pids?: number[]) => void;
/**
* 关闭某个key的监听 只有当前系统上所有的key都关闭了,程序才会停止实时监控进程信息
* @param key
*/
close: (key: string) => void;
/**
* 对某个key的监听进程id切换设置
* 监听特定进程信息(只是起到过滤作用)
* @param key
* @param pids
*/
pids: (key: string, pids: number[]) => void;
/**
* get sys all pid 获取系统所有的进程pid信息
* @param ppid
*/
get_all_pid(ppid?: number): {
pid: number;
cpu: number;
ppid: number;
}[];
/**
* kill process 可以关闭所有的子进程
* @param pid
* @param kill_all_children default false
*/
kill_process(pid: number, kill_all_children?: boolean): void;
/**
* 使用子线程遍历全部的文件与数量
* @param folder_name
* @param on
*/
on_folder_size(folder_name: string, on: (file_num: number, total_size: number) => void): void;
/**
* 停止对某个目录的数量统计
* @param folder_name
*/
stop_folder_size(folder_name: string): void;
get_system_proxy_for_windows(): {
enabled: boolean;
ip: boolean;
port: number;
bypass?: string;
useForLocal?: boolean;
};
set_system_proxy_for_windows(data: {
enabled: boolean;
ip: boolean;
port: number;
bypass?: string;
useForLocal?: boolean;
}): boolean;
get_system_proxy_for_mac(): {
name: string;
proxies: {
type: number;
enabled: boolean;
ip: string;
port: number;
bypass?: string;
useForLocal?: boolean;
}[];
bypass?: string;
}[];
set_system_proxy_for_mac(data: {
name: string;
proxies: {
type: number;
enabled: boolean;
ip: string;
port: number;
bypass?: string;
useForLocal?: boolean;
}[];
bypass?: string;
}[]): boolean;
/**
* 判断当前进程是否以管理员/root权限运行
*/
is_admin(): boolean;
/**
* 在 Windows Service 中,
* 使用 CreateProcessAsUser 在当前登录用户桌面启动程序
*
* ⚠️ 仅 Windows 生效
* ⚠️ Service 必须以 LocalSystem 运行
*
* @param exe_path exe 完整路径
* @param cwd 工作目录
* @param args
*/
launch_process_as_user_for_win_service(exe_path: string, args?: string, cwd?: string): number;
launch_process_as_user_for_win_service_console(exe_path: string, args?: string, cwd?: string, on_data?: (data: string) => void, on_done?: () => void): void;
get_all_processes(): {
pid: number;
name: string;
}[];
get_username_by_uid(uid: number): string;
get_all_users(): ({
uid: number;
username: string;
} | {
groups: string[];
username: string;
domain: string;
sid: string;
})[];
get_file_owner(file_path: string): {
username: string;
domain: string;
sid: string;
type: string;
};
}
export declare const node_process_watcher: node_process_watcher_type;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.node_process_watcher = void 0;
const native = require("../build/Release/node-process-watcher.node");
exports.node_process_watcher = native;
const native = require("../build/Release/node-process-watcher.node")
export interface process_info {
id: number;
name: string;
user_name: string;
mem: number; // 内存占用情况
cpu: number; // 使用率
}
export interface node_process_watcher_type {
/**
* 监听进程,需要提供一个 key
* @param key
* @param call
* @param pids 监听特定进程信息(只是起到过滤作用)
*/
on: (key: string, call: (list: process_info[]) => any, pids?: number[]) => void;
/**
* 关闭某个key的监听 只有当前系统上所有的key都关闭了,程序才会停止实时监控进程信息
* @param key
*/
close: (key: string) => void;
/**
* 对某个key的监听进程id切换设置
* 监听特定进程信息(只是起到过滤作用)
* @param key
* @param pids
*/
pids: (key: string, pids: number[]) => void;
/**
* get sys all pid 获取系统所有的进程pid信息
* @param ppid
*/
get_all_pid(ppid?: number): { pid: number, cpu: number, ppid: number }[];
/**
* kill process 可以关闭所有的子进程
* @param pid
* @param kill_all_children default false
*/
kill_process(pid: number, kill_all_children ?: boolean): void;
/**
* 使用子线程遍历全部的文件与数量
* @param folder_name
* @param on
*/
on_folder_size(folder_name: string, on: (file_num: number, total_size: number) => void): void;
/**
* 停止对某个目录的数量统计
* @param folder_name
*/
stop_folder_size(folder_name: string):void;
get_system_proxy_for_windows(): {
enabled: boolean
ip: boolean
port: number
bypass?: string
useForLocal?: boolean
};
set_system_proxy_for_windows(data: {
enabled: boolean
ip: boolean
port: number
bypass?: string
useForLocal?: boolean
}): boolean;
get_system_proxy_for_mac(): {
name: string
proxies: {
type: number // 1 http, 2 https
enabled: boolean
ip: string
port: number
bypass?: string
useForLocal?: boolean
}[]
bypass?: string
}[];
set_system_proxy_for_mac(data: {
name: string
proxies: {
type: number // 1 http, 2 https
enabled: boolean
ip: string
port: number
bypass?: string
useForLocal?: boolean
}[]
bypass?: string
}[]): boolean;
/**
* 判断当前进程是否以管理员/root权限运行
*/
is_admin(): boolean;
/**
* 在 Windows Service 中,
* 使用 CreateProcessAsUser 在当前登录用户桌面启动程序
*
* ⚠️ 仅 Windows 生效
* ⚠️ Service 必须以 LocalSystem 运行
*
* @param exe_path exe 完整路径
* @param cwd 工作目录
* @param args
*/
launch_process_as_user_for_win_service(
exe_path: string,
args?: string,
cwd?: string
): number;
launch_process_as_user_for_win_service_console(
exe_path: string,
args?: string,
cwd?: string,
on_data?:(data: string)=>void,
on_done?:()=>void
):void;
// 获取全部的正在运行的进程信息
get_all_processes():{pid:number,name:string}[];
get_username_by_uid(uid:number):string;
get_all_users(): ({uid:number,username:string} |
{
groups:string[],
username:string,
domain:string,
sid:string
})[];
get_file_owner(file_path:string):{
username:string,
domain:string,
sid:string,
type:string
}
}
export const node_process_watcher: node_process_watcher_type = native;
+14
-11
{
"name": "node-process-watcher",
"version": "1.6.3",
"version": "1.6.5",
"description": "Get process information in real time",
"main": "./src/index.js",
"types": "./src/index.d.ts",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"repository": {

@@ -13,6 +13,7 @@ "type": "git",

"install": "prebuild-install --verbose || npm run install_build",
"install_build": "npm install node-addon-api node-gyp --save-dev && node-gyp rebuild --release",
"install_build": "node-gyp rebuild --release",
"cc-rebuild": " node-gyp rebuild",
"cc-configure": "node-gyp configure",
"go": "npm run cc-configure && node-gyp build --debug"
"go": "npm run cc-configure && node-gyp build --debug",
"build-ts": "tsc"
},

@@ -39,3 +40,5 @@ "keywords": [

"dependencies": {
"prebuild-install": "^7.1.2"
"prebuild-install": "^7.1.2",
"node-addon-api": "^8.6.0",
"node-gyp": "^10.3.1"
},

@@ -45,10 +48,10 @@ "files": [

"common.gypi",
"src/**"
"src/**",
"lib/**"
],
"devDependencies": {
"mocha": "^10.7.3",
"node-addon-api": "^8.6.0",
"node-gyp": "^10.3.1",
"prebuild": "^13.0.1"
"prebuild": "^13.0.1",
"@types/node": "^25.4.0",
"typescript": "^5.9.3"
}
}

@@ -345,27 +345,6 @@

// widnwos 下才注册的哈桑农户
#ifdef _WIN32
// windwos 下才注册的函数
Napi::Value LaunchAsUser(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (info.Length() < 2 ||
!info[0].IsString() ||
!info[1].IsString()) {
Napi::TypeError::New(
env,
"usage: launchAsUser(exePath: string, cwd: string)"
).ThrowAsJavaScriptException();
return env.Null();
}
std::u16string exe16 = info[0].As<Napi::String>().Utf16Value();
std::u16string cwd16 = info[1].As<Napi::String>().Utf16Value();
std::wstring exePath(exe16.begin(), exe16.end());
std::wstring cwd(cwd16.begin(), cwd16.end());
bool result = LaunchProcessAsUser(exePath, cwd);
return Napi::Boolean::New(env, result);
}
#endif

@@ -425,4 +404,5 @@

"launch_process_as_user_for_win_service",
Napi::Function::New(env, LaunchAsUser)
Napi::Function::New(env, LaunchUserWindowsProcess)
);
exports.Set("launch_process_as_user_for_win_service_console", Napi::Function::New(env, LaunchUserConsoleProcess));
exports.Set("get_file_owner", Napi::Function::New(env, GetFileOwner));

@@ -429,0 +409,0 @@ #endif

@@ -74,7 +74,6 @@ //

// windwos 下才注册的函数
bool LaunchProcessAsUser(
const std::wstring& exePath,
const std::wstring& cwd
);
Napi::Value LaunchUserWindowsProcess(const Napi::CallbackInfo& info);
Napi::Value LaunchUserConsoleProcess(const Napi::CallbackInfo& info);
struct WindowsUser {

@@ -81,0 +80,0 @@ std::string username;

@@ -605,58 +605,4 @@ #ifdef _WIN32

bool LaunchProcessAsUser(const std::wstring& exePath,const std::wstring& cwd) {
DWORD sessionId = WTSGetActiveConsoleSessionId();
if (sessionId == 0xFFFFFFFF) return false;
HANDLE userToken = NULL;
if (!WTSQueryUserToken(sessionId, &userToken)) return false;
HANDLE primaryToken = NULL;
if (!DuplicateTokenEx(
userToken,
TOKEN_ALL_ACCESS,
NULL,
SecurityImpersonation,
TokenPrimary,
&primaryToken
)) {
CloseHandle(userToken);
return false;
}
LPVOID env = NULL;
CreateEnvironmentBlock(&env, primaryToken, FALSE);
STARTUPINFOW si{};
si.cb = sizeof(si);
si.lpDesktop = (LPWSTR)L"winsta0\\default";
PROCESS_INFORMATION pi{};
BOOL ok = CreateProcessAsUserW(
primaryToken,
exePath.c_str(),
NULL,
NULL,
NULL,
FALSE,
CREATE_UNICODE_ENVIRONMENT,
env,
cwd.c_str(),
&si,
&pi
);
if (env) DestroyEnvironmentBlock(env);
CloseHandle(primaryToken);
CloseHandle(userToken);
if (ok) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return ok;
}
std::vector<ProcessInfoShort> getAllProcesses() {

@@ -869,4 +815,250 @@ std::vector<ProcessInfoShort> processes;

Napi::Value LaunchUserWindowsProcess(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (info.Length() < 1 || !info[0].IsString()) {
Napi::TypeError::New(env, "Expected exe path").ThrowAsJavaScriptException();
return env.Null();
}
std::u16string u16path = info[0].ToString().Utf16Value();
std::wstring path(u16path.begin(), u16path.end());
std::wstring args = L"";
std::wstring cwd = L"";
if (info.Length() >= 2 && info[1].IsString()) {
std::u16string u16args = info[1].ToString().Utf16Value();
args = std::wstring(u16args.begin(), u16args.end());
}
if (info.Length() >= 3 && info[2].IsString()) {
std::u16string u16cwd = info[2].ToString().Utf16Value();
cwd = std::wstring(u16cwd.begin(), u16cwd.end());
}
// 构建命令行: "path" args
std::wstring commandLine = L"\"" + path + L"\" " + args;
std::vector<wchar_t> cmd(commandLine.begin(), commandLine.end());
cmd.push_back(0); // null-terminate
// 获取当前活动用户 Session
DWORD sessionId = WTSGetActiveConsoleSessionId();
if (sessionId == 0xFFFFFFFF) return Napi::Number::New(env, -1);
HANDLE userToken = NULL;
if (!WTSQueryUserToken(sessionId, &userToken)) return Napi::Number::New(env, -1);
HANDLE primaryToken = NULL;
if (!DuplicateTokenEx(
userToken,
TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID,
NULL,
SecurityImpersonation,
TokenPrimary,
&primaryToken)) {
CloseHandle(userToken);
return Napi::Number::New(env, -1);
}
LPVOID environment = NULL;
if (!CreateEnvironmentBlock(&environment, primaryToken, FALSE)) {
environment = NULL;
}
STARTUPINFOW si{};
si.cb = sizeof(si);
si.lpDesktop = L"winsta0\\default"; // 指定桌面
DWORD flags = CREATE_UNICODE_ENVIRONMENT;
PROCESS_INFORMATION pi{};
BOOL ok = CreateProcessAsUserW(
primaryToken,
NULL,
cmd.data(),
NULL,
NULL,
FALSE,
flags,
environment,
cwd.empty() ? NULL : cwd.c_str(),
&si,
&pi
);
if (environment) DestroyEnvironmentBlock(environment);
CloseHandle(primaryToken);
CloseHandle(userToken);
if (ok) {
DWORD pid = pi.dwProcessId;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return Napi::Number::New(env, pid);
}
return Napi::Number::New(env, -1);
}
class ProcessWorker : public Napi::AsyncWorker {
public:
ProcessWorker(const Napi::Env& env,
const std::wstring& exe_path,
const std::wstring& args,
const std::wstring& cwd,
Napi::Function dataCallback,
Napi::Function doneCallback)
: Napi::AsyncWorker(doneCallback), // AsyncWorker 的默认回调用作完成回调
exe_path_(exe_path), args_(args), cwd_(cwd),
tsfn_(Napi::ThreadSafeFunction::New(env, dataCallback, "OnData", 0, 1))
{}
~ProcessWorker() {
tsfn_.Release();
}
void Execute() override {
SECURITY_ATTRIBUTES sa{ sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE };
HANDLE hStdOutRead = nullptr;
HANDLE hStdOutWrite = nullptr;
if (!CreatePipe(&hStdOutRead, &hStdOutWrite, &sa, 0)) {
SetError("Failed to create stdout pipe");
return;
}
PROCESS_INFORMATION pi{ 0 };
STARTUPINFOW si{ 0 };
si.cb = sizeof(STARTUPINFOW);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = hStdOutWrite;
si.hStdError = hStdOutWrite;
si.hStdInput = nullptr;
std::wstring cmd = L"\"" + exe_path_ + L"\" " + args_;
// 获取当前活动用户 Session
DWORD sessionId = WTSGetActiveConsoleSessionId();
HANDLE userToken = NULL;
WTSQueryUserToken(sessionId, &userToken);
HANDLE primaryToken = NULL;
DuplicateTokenEx(
userToken,
TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID,
NULL,
SecurityImpersonation,
TokenPrimary,
&primaryToken);
LPVOID environment = NULL;
if (!CreateEnvironmentBlock(&environment, primaryToken, FALSE)) {
environment = NULL;
}
DWORD flags = CREATE_UNICODE_ENVIRONMENT;
BOOL ok = CreateProcessAsUserW(
primaryToken,
NULL,
cmd.data(),
NULL,
NULL,
TRUE,
flags,
environment,
cwd_.empty() ? nullptr : cwd_.c_str(),
&si,
&pi
);
CloseHandle(hStdOutWrite); // 关闭写端,子进程可以写
if (environment) DestroyEnvironmentBlock(environment);
CloseHandle(primaryToken);
CloseHandle(userToken);
char buffer[4096];
DWORD bytesRead;
while (ReadFile(hStdOutRead, buffer, sizeof(buffer)-1, &bytesRead, nullptr) && bytesRead > 0) {
// buffer[bytesRead] = '\0';
if(bytesRead==0) break;
std::string output(buffer, bytesRead);
tsfn_.BlockingCall([output](Napi::Env env, Napi::Function jsCallback) {
jsCallback.Call({ Napi::String::New(env, output) });
});
}
CloseHandle(hStdOutRead);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
private:
std::wstring exe_path_;
std::wstring args_;
std::wstring cwd_;
Napi::ThreadSafeFunction tsfn_;
};
Napi::Value LaunchUserConsoleProcess(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// 参数数量检查
if (info.Length() < 5) {
Napi::TypeError::New(env, "Expected 5 arguments: exePath, args, cwd, dataCallback, doneCallback").ThrowAsJavaScriptException();
return env.Null();
}
// exePath
if (!info[0].IsString()) {
Napi::TypeError::New(env, "exePath must be a string").ThrowAsJavaScriptException();
return env.Null();
}
std::u16string u16path = info[0].ToString().Utf16Value();
std::wstring exe_path(u16path.begin(), u16path.end());
// args
if (!info[1].IsString()) {
Napi::TypeError::New(env, "args must be a string").ThrowAsJavaScriptException();
return env.Null();
}
std::u16string u16args = info[1].ToString().Utf16Value();
std::wstring args(u16args.begin(), u16args.end());
// cwd
if (!info[2].IsString()) {
Napi::TypeError::New(env, "cwd must be a string").ThrowAsJavaScriptException();
return env.Null();
}
std::u16string u16cwd = info[2].ToString().Utf16Value();
std::wstring cwd(u16cwd.begin(), u16cwd.end());
// dataCallback
if (!info[3].IsFunction()) {
Napi::TypeError::New(env, "dataCallback must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function dataCallback = info[3].As<Napi::Function>();
// doneCallback
if (!info[4].IsFunction()) {
Napi::TypeError::New(env, "doneCallback must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function doneCallback = info[4].As<Napi::Function>();
// 创建并队列异步任务
ProcessWorker* worker = new ProcessWorker(env, exe_path, args, cwd, dataCallback, doneCallback);
worker->Queue();
return env.Null();
}
#pragma clang diagnostic pop
#endif
export interface process_info {
id: number;
name: string;
user_name: string;
mem: number; // 内存占用情况
cpu: number; // 使用率
}
export interface node_process_watcher_type {
/**
* 监听进程,需要提供一个 key
* @param key
* @param call
* @param pids 监听特定进程信息(只是起到过滤作用)
*/
on: (key: string, call: (list: process_info[]) => any, pids?: number[]) => void;
/**
* 关闭某个key的监听 只有当前系统上所有的key都关闭了,程序才会停止实时监控进程信息
* @param key
*/
close: (key: string) => void;
/**
* 对某个key的监听进程id切换设置
* 监听特定进程信息(只是起到过滤作用)
* @param key
* @param pids
*/
pids: (key: string, pids: number[]) => void;
/**
* get sys all pid 获取系统所有的进程pid信息
* @param ppid
*/
get_all_pid(ppid?: number): { pid: number, cpu: number, ppid: number }[];
/**
* kill process 可以关闭所有的子进程
* @param pid
* @param kill_all_children default false
*/
kill_process(pid: number, kill_all_children ?: boolean): void;
/**
* 使用子线程遍历全部的文件与数量
* @param folder_name
* @param on
*/
on_folder_size(folder_name: string, on: (file_num: number, total_size: number) => void);
/**
* 停止对某个目录的数量统计
* @param folder_name
*/
stop_folder_size(folder_name: string);
get_system_proxy_for_windows(): {
enabled: boolean
ip: boolean
port: number
bypass?: string
useForLocal?: boolean
};
set_system_proxy_for_windows(data: {
enabled: boolean
ip: boolean
port: number
bypass?: string
useForLocal?: boolean
}): boolean;
get_system_proxy_for_mac(): {
name: string
proxies: {
type: number // 1 http, 2 https
enabled: boolean
ip: string
port: number
bypass?: string
useForLocal?: boolean
}[]
bypass?: string
}[];
set_system_proxy_for_mac(data: {
name: string
proxies: {
type: number // 1 http, 2 https
enabled: boolean
ip: string
port: number
bypass?: string
useForLocal?: boolean
}[]
bypass?: string
}[]): boolean;
/**
* 判断当前进程是否以管理员/root权限运行
*/
is_admin(): boolean;
/**
* 在 Windows Service 中,
* 使用 CreateProcessAsUser 在当前登录用户桌面启动程序
*
* ⚠️ 仅 Windows 生效
* ⚠️ Service 必须以 LocalSystem 运行
*
* @param exe_path exe 完整路径
* @param cwd 工作目录
* @param args
*/
launch_process_as_user_for_win_service(
exe_path: string,
cwd: string,
args?: string
): boolean;
// 获取全部的正在运行的进程信息
get_all_processes():{pid:number,name:string}[];
get_username_by_uid(uid:number):string;
get_all_users(): ({uid:number,username:string} |
{
groups:string[],
username:string,
domain:string,
sid:string
})[];
get_file_owner(file_path:string):{
username:string,
domain:string,
sid:string,
type:string
}
}
export declare const node_process_watcher: node_process_watcher_type;
const node_process_watcher = require("../build/Release/node-process-watcher.node")
module.exports.node_process_watcher = node_process_watcher;