cutebe 发表于 2026-7-10 16:51:42

办公软件WPS的JSA中实现注销/重启/关机

办公软件WPS的表格:通过ExecuteExcel4Macro调用WinAPI实现

  操作前请先保存好数据!

执行前面三个函数可看到效果:
function 注销测试(){let 注销=0;操作系统动作(注销);}
function 重启测试(){let 重启=2;操作系统动作(重启);}
function 关机测试(){let 关机=1;操作系统动作(关机);}

function 操作系统动作(动作){
        let 当前进程伪句柄=获取当前进程();
        let 调整权限=0x20;
        let 当前进程令牌=打开进程令牌(获取当前进程(),调整权限);        //一、获取令牌
       
        let 内存句柄=申请本地内存(16);        //令牌特权结构16字节
        let 内存地址=锁定本地内存(内存句柄);        //用于写入
        let 条目数=1,特权开启=2;
        数组写入内存(内存地址,[条目数]);数组写入内存(内存地址+12,[特权开启]);        //写入条目数与属性
        let 系统关闭特权="SeShutdownPrivilege";
        let 获取结果=获取特权标志符(系统关闭特权,内存地址+4);        //二、获取LUID:本地标号 在 令牌特权结构 中偏移4字节
        解锁本地内存(内存句柄);

        内存地址=锁定本地内存(内存句柄);        //用于读取
        let 修改结果=修改令牌特权(当前进程令牌,内存地址);        //三、修改令牌权限
        解锁本地内存(内存句柄);释放本地内存(内存句柄);
       
        let 注销=0,重启=2,关机=1,关闭电源=8;let 强制=4,超时强制=0x10;
        let 操作系统原因=0x20000,其他计划关闭=0x80000000;
        let 操作=动作|超时强制,原因=操作系统原因|其他计划关闭;
        let 动作结果=系统关闭操作(操作,原因);        //四、系统操作
}


其他用到的函数:
function 获取当前进程(){        //返回进程伪句柄
        const 执行宏调用=ExecuteExcel4Macro;
        let 进程伪句柄=执行宏调用(`CALL("Kernel32","GetCurrentProcess","J")`);
        return 进程伪句柄;
}
function 打开进程令牌(进程句柄,访问类型){        //关机、重启、注销
        const 执行宏调用=ExecuteExcel4Macro;
        let 令牌句柄=执行宏调用(`CALL("Advapi32","OpenProcessToken","3JJN",${进程句柄},${访问类型},0)`);
        return 令牌句柄;
}
function 获取特权标志符(特权名,本地标号地址){        //本地标号(本地唯一标识符LUID)占64位,即8字节。
        const 执行宏调用=ExecuteExcel4Macro;
        let 获取结果=执行宏调用(`CALL("Advapi32","LookupPrivilegeValueA","AJFJ",0,"${特权名}",${本地标号地址})`);
        return 获取结果;
}
function 修改令牌特权(令牌号,新特权地址){
        const 执行宏调用=ExecuteExcel4Macro;
        let 修改结果=执行宏调用(`CALL("Advapi32","AdjustTokenPrivileges","AJAJJJJ",${令牌号},0,${新特权地址},0,0,0)`);
        return 修改结果;
}
function 系统关闭操作(操作,原因){        //关机、重启、注销
        const 执行宏调用=ExecuteExcel4Macro;
        let 注销=0,重启=2,关机=1,关闭电源=8;let 强制=4,超时强制=0x10;
        let 操作结果=执行宏调用(`CALL("User32","ExitWindowsEx","AJJ",${操作},${原因})`);
        return 操作结果;
}

function 申请本地内存(字节数){        //返回内存句柄
        const 执行宏调用=ExecuteExcel4Macro;
        const 内存句柄=执行宏调用(`CALL("Kernel32","LocalAlloc","JJJ",2,${字节数})`);
        if(内存句柄){
                return 内存句柄;
        }else{console.log("未能分配内存!");}
}
function 释放本地内存(内存句柄){
        const 执行宏调用=ExecuteExcel4Macro;
        执行宏调用(`CALL("Kernel32","LocalFree","JJ",${内存句柄})`);        //释放内存
}
function 锁定本地内存(内存句柄){        //返回内存地址
        const 执行宏调用=ExecuteExcel4Macro;
        const 内存地址=执行宏调用(`CALL("Kernel32","LocalLock","JJ",${内存句柄})`);
        if(内存地址){
                return 内存地址;
        }else{console.log("未找到内存地址!");}
}
function 解锁本地内存(内存句柄){
        const 执行宏调用=ExecuteExcel4Macro;
        执行宏调用(`CALL("Kernel32","LocalUnlock","JJ",${内存句柄})`);        //解锁
}

function 数组写入内存(内存地址,数组){
        const 执行宏调用=ExecuteExcel4Macro,写入字节=4;
        for(let 偏移=i=0;i<数组.length;i++){        //写入
                执行宏调用(`CALL("Kernel32","RtlMoveMemory","2JNJ",${内存地址+偏移},${数组},${写入字节})`);
                偏移+=写入字节;
        }
}

y9032 发表于 2026-7-10 17:22:31

一起浇一浇,灌一灌,预祝一天心情好!

valar263 发表于 2026-7-10 18:09:39

感谢分享

zhanglei1371 发表于 2026-7-10 18:44:56

感谢分享

yyz219195888 发表于 2026-7-11 07:16:56

这个强大

it323 发表于 2026-7-11 07:36:02

了解一下。

ebaqiang 发表于 2026-7-11 11:24:25

没有接触过,学习了。

bird202601 发表于 2026-7-11 12:29:20

谢谢分享

ZMLoveLH 发表于 2026-7-11 13:40:27

看看楼主的文章,学习学习

ebaqiang 发表于 2026-7-12 05:08:34

我是小白,向老师学习!

seven0 发表于 2026-8-11 15:36:21

支持一下,谢谢分享。
页: [1]
查看完整版本: 办公软件WPS的JSA中实现注销/重启/关机