吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1136|回复: 7
上一主题 下一主题
收起左侧

[原创工具] WebConsole_web控制台,通过手机浏览器遥控电脑

  [复制链接]
跳转到指定楼层
楼主
alomoi 发表于 2026-1-27 14:06 回帖奖励
本帖最后由 alomoi 于 2026-1-27 14:14 编辑

用你的手机当遥控器,对电脑进行一些简单“遥控”
支持自定义命令,可以添加你自己的程序到“遥控”菜单,一键启动



程序首次运行会弹出日志窗口,提示web服务运行的端口(后续可以自行修改)及默认用户名密码
日志界面仅在首次运行时弹出,后续可通过程序托盘图标右键,选择“系统日志”进入


通过程序托盘图标右键,选择“自定义命令”可自行添加需要“遥控”启动的程序
注意:如果你添加的程序包括参数和配置文件,需为配置文件填写完整路径(如fprc示例)


在浏览器中通过IP+端口可访问web控制台页面,登录之后可看到常驻命令和添加的自定义命令,点击对应的按钮即可执行


点击下方的“系统设置”可修改用户名、密码及服务运行端口



程序使用aardio编写,编译之后的程序有误报情况
不放心的可通过以下源码自行编译
[AAuto] 纯文本查看 复制代码
import process.mutex;
var appId = "{A7B8C9D0-E1F2-4A5B-B6C7-D8E9F0A1B2C3}";
var mutex = process.mutex(appId);
if(mutex.conflict){
    import winex;
    var hwnd = winex.find( , "web控制台-日志");
    if(hwnd){
        win.showForeground(hwnd);
        win.flash(hwnd, 1/*_FLASHW_CAPTION*/ | 4/*_FLASHW_TRAY*/);
    }
    return;
};

import win.ui.menu;
import win.util.tray;
import win.ui.grid;
import crypt;
import fsys.config;
import inet.url;
import gdip.snap;
import fsys.dlg;
import process;
import wsock.tcp.asyncHttpServer;
/*DSG{{*/
var winform = win.form(text="web控制台-日志";right=544;bottom=320;max=false)
winform.add(
edit={cls="edit";left=22;top=28;right=521;bottom=284;ah=1;aw=1;edge=1;multiline=1;z=1}
)
/*}}*/

var config = fsys.config("/config/"); 

if(!config.auth.user){
        initialization = true
    config.auth.user = "admin";
    config.auth.pwdHash = crypt.sha256("123456");
    config.commands.calc = { cmd = "calc.exe"; title = "打开计算器" };
    config.commands.notepad = { cmd = "notepad.exe"; title = "打开记事本" };
    config.saveAll();
}

var showCommandEditor = function(){
/*DSG{{*/
var frmChild = win.form(text="web控制台-自定义命令";right=565;bottom=385;parent=winform)
frmChild.add(
btnAdd={cls="button";text="新增命令";left=332;top=316;right=431;bottom=360;ah=1;aw=1;z=2};
btnDel={cls="button";text="删除选中";left=450;top=316;right=549;bottom=360;ah=1;aw=1;z=3};
listview={cls="listview";left=15;top=15;right=551;bottom=297;ah=1;aw=1;edge=1;fullRow=1;z=1}
)
/*}}*/
    var grid = win.ui.grid(frmChild.listview);
    grid.columns = {
        {"路径键名 (URL)"; 120};
        {"显示标题"; 120};
        {"执行程序/路径"; -1}
    }

    var reloadData = function(){
        grid.clear();
        for(name, cfg in config.commands){
            if( type(cfg) == type.table ){ 
                grid.addItem({ name; cfg.title; cfg.cmd });
            }
        }
    }
    reloadData();

    frmChild.btnAdd.oncommand = function(id,event){
        var path = fsys.dlg.open("所有文件|*.*||", "选择要执行的程序");
        if(path){
            var name = io.splitpath(path).name;
            var key = name;
            var i = 1;
            while(config.commands[key]){
                key = name + i;
                i++;
            }
            config.commands[key] = { cmd = path; title = name };
            config.saveAll();
            reloadData();
        }
    }

    frmChild.btnDel.oncommand = function(id,event){
        var selIdx = frmChild.listview.selIndex;
        if(!selIdx) return frmChild.msgbox("请先选择要删除的项");

        var key = frmChild.listview.getItemText(selIdx, 1);
        if(frmChild.msgboxTest("确定要删除命令 ["+key+"] 吗?")){
            config.commands[key] = null;
            config.saveAll();
            reloadData();
        }
    }

    grid.onEditChanged = function(text, row, col){
        var key = frmChild.listview.getItemText(row, 1);
        var cfg = config.commands[key];

        if(col == 1){
            if(#text && text != key){
                config.commands[text] = cfg;
                config.commands[key] = null;
            }
        }
        elseif(col == 2){
            cfg.title = text;
        }
        elseif(col == 3){
            cfg.cmd = text;
        }

        config.saveAll();
        return true; 
    }
    frmChild.show();
}

var server = wsock.tcp.asyncHttpServer();
var tray = win.util.tray(winform)
tray.tip = "web控制台-服务端"
winform.onTrayMessage = {
    [0x205 /*_WM_RBUTTONUP*/ ] = function(id){
        var popmenu = win.ui.popmenu(winform);
        popmenu.add("系统日志", function(id){ 
            winform.show();
            win.setForeground(winform.hwnd);
            win.show(winform.hwnd, 0x9/*_SW_RESTORE*/); 
        });
        popmenu.add("自定义命令", function(id){ 
            showCommandEditor(); 
        });
        popmenu.add();
        popmenu.add("访问web控制台", function(id){
            raw.execute(server.getUrl());
        });
        popmenu.add();
        popmenu.add("🔗吾爱破解论坛", function(id){
            process.execute("https://www.52pojie.cn/");
        });
        popmenu.add("退出程序", function(id){
            winform.close(); 
            win.quitMessage();
        });
        popmenu.popup();
    };
    [0x203 /*_WM_LBUTTONDBLCLK*/] = function(id){ winform.show(); };
}
winform.onClose = function(){ winform.show(false); return false; }

server.run(
    function(response, request){
        var msgPage = function(title, msg, isError){
            var actionUrl = isError ? "javascript:history.back();" : "/";
            var actionText = isError ? "返回重试" : "返回首页";
            return `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
            <style>
                body{ font-family:sans-serif; display:flex; justify-content:center; align-items:center; height:100vh; margin:0; background:#f0f2f5;}
                .card{ background:white; padding:30px; border-radius:8px; box-shadow:0 2px 10px rgba(0,0,0,0.1); width:90%; max-width:300px; text-align:center;}
                .icon{ font-size:48px; margin-bottom:10px; color:` + (isError ? "#e74c3c" : "#2ecc71") + `;}
                h2{ margin:10px 0; color:#333;} p{ color:#666; margin-bottom:20px;}
                .btn{ display:inline-block; text-decoration:none; background:#0078d4; color:white; padding:10px 20px; border-radius:4px; font-size:16px; border:none; cursor:pointer;}
                .timer{ font-size:12px; color:#999; margin-top:15px;}
            </style></head>
            <body>
                <div class="card">
                    <div class="icon">` + (isError ? "&#10005;" : "&#10003;") + `</div>
                    <h2>` + title + `</h2>
                    <p>` + msg + `</p>
                    <a href="` + actionUrl + `" class="btn" id="btnAction">` + actionText + ` (5)</a>
                    <div class="timer">页面将在 5 秒后自动跳转</div>
                </div>
                <script>
                    (function(){
                        var wait = 5;
                        var btn = document.getElementById('btnAction');
                        var actionName = "` + actionText + `";
                        var url = "` + actionUrl + `";
                        var timer = setInterval(function(){
                            wait--;
                            if(wait > 0){
                                btn.innerText = actionName + " (" + wait + ")";
                            } else {
                                clearInterval(timer);
                                if(url.indexOf('javascript:') === 0){
                                    history.back();
                                } else {
                                    location.href = url;
                                }
                            }
                        }, 1000);
                    })();
                </script>
            </body></html>`;
        }
        var confirmPage = function(title, msg, actionPath, btnText) {
            return `
            <!DOCTYPE html>
            <html><head>
                <meta charset="utf-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <style>
                    body{ font-family:sans-serif; display:flex; justify-content:center; align-items:center; height:100vh; margin:0; background:#f0f2f5;}
                    .card{ background:white; padding:30px; border-radius:8px; box-shadow:0 2px 10px rgba(0,0,0,0.1); width:90%; max-width:300px; text-align:center;}
                    .icon{ font-size:48px; margin-bottom:10px; color:#f39c12;}
                    h2{ margin:10px 0; color:#333;} p{ color:#666; margin-bottom:20px;}
                    .btn-danger{ display:inline-block; text-decoration:none; background:#e74c3c; color:white; padding:10px 20px; border-radius:4px; font-size:16px; border:none; cursor:pointer;}
                    .btn-cancel{ display:inline-block; text-decoration:none; background:#95a5a6; color:white; padding:10px 20px; border-radius:4px; font-size:16px; border:none; cursor:pointer; margin-left:10px;}
                </style></head>
            <body>
                <div class="card">
                <div class="icon">&#9888;</div>
                <h2>` + title + `</h2>
                <p>` + msg + `</p>
                <a href="` + actionPath + `?confirm=1" class="btn-danger">` + btnText + `</a>
                <a href="/" class="btn-cancel">取消</a>
                </div>
            </body></html>`;
        }

        if (request.path == "/login"){
            if(request.method == "POST"){
                var user = request.post["user"];
                var pwd = request.post["pwd"];
                if(user == config.auth.user && crypt.sha256(pwd) == config.auth.pwdHash){
                    winform.edit.print(tostring(time()), request.remoteAddr, user,"登录成功");
                    session.loggedIn = true; 
                    response.redirect("/"); 
                    return;
                }
                winform.edit.print(tostring(time()), request.remoteAddr, user,"登录失败");
                response.write(msgPage("登录失败", "用户名或密码错误!", true));  
                return;
            }
            response.write(`
            <!DOCTYPE html>
            <html><head>
                <meta charset="utf-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <style>
                    body{ font-family:sans-serif; display:flex; justify-content:center; align-items:center; min-height:100vh; margin:0; background:#f0f2f5;}
                    .container{ background:white; padding:30px; border-radius:8px; box-shadow:0 2px 10px rgba(0,0,0,0.1); width:90%; max-width:320px;}
                    h2{ text-align:center; color:#333; margin-top:0;}
                    label{ display:block; margin-bottom:5px; color:#666; font-size:14px;}
                    input{ width:100%; padding:12px; margin-bottom:20px; border:1px solid #ddd; box-sizing:border-box; border-radius:4px; font-size:16px;}
                    button{ width:100%; padding:12px; background:#0078d4; color:white; border:none; border-radius:4px; cursor:pointer; font-size:16px; transition: background 0.3s;}
                    button:hover{ background:#005a9e; }
                </style>
            </head>
            <body>
            <div class="container">
                <h2>Web控制台登录</h2>
                <form method="post" action="/login">
                    <label>用户名</label>
                    <input name="user" type="text" placeholder="请输入用户名" required>
                    <label>密码</label>
                    <input name="pwd" type="password" placeholder="请输入密码" required>
                    <button type="submit">登录</button>
                </form>
            </div>
            </body></html>
            `);
            return;
        }

        if(!session.loggedIn){
            response.redirect("/login"); 
            return;
        }

        if(request.path != "/favicon.ico"){
            if(request.path = "/main.aardio"){
                winform.edit.print(tostring(time()), request.remoteAddr, request.method, "/");
            }
            else{
                winform.edit.print(tostring(time()), request.remoteAddr, request.method, request.path);
            } 
        }

        if(request.path == "/logout"){
            session.loggedIn = null;
            response.redirect("/login");
            return;
        }

        var cmdName = string.slice(request.path, 2); 
        if( !string.indexOf(cmdName,"/") ){
            var cfgCmd = config.commands[cmdName];
            if(cfgCmd && type(cfgCmd) == type.table){
                process(cfgCmd.cmd);
                winform.edit.print(tostring(time()), "执行自定义命令: " + (cfgCmd.title || cmdName));
                response.write(msgPage("指令已发送", (cfgCmd.title || cmdName), false)); 
                return;
            }
        }

        select(request.path) {
            case "/@settings" {
                if (request.method == "POST") {
                    var newUser = request.post["newuser"];
                    var newPwd = request.post["newpwd"];
                    var portInput = request.post["newport"];

                    if( newUser && #newUser && newPwd && #newPwd ){
                        config.auth.user = newUser;
                        config.auth.pwdHash = crypt.sha256(newPwd);
                        if( !portInput || !#string.trim(portInput) ){
                            config.auth.port = 0;
                        } 
                        else {
                            var p = tonumber(portInput);
                            if(p !== null && p >= 0 && p <= 65535){
                                config.auth.port = p;
                            }
                        }
                        config.auth.save();
                        winform.edit.print(tostring(time()), request.remoteAddr, newUser,"已修改配置");
                        response.write(msgPage("修改成功", "配置已更新。若修改了端口,请手动重启程序生效。", false));
                        return; 
                    }
                    response.write(msgPage("修改失败", "用户名或密码不能为空。", true));  
                    return;
                }
                response.write(`
                <!DOCTYPE html>
                <html><head>
                    <meta charset="utf-8">
                    <meta name="viewport" content="width=device-width, initial-scale=1.0">
                    <style>
                        body{ font-family:sans-serif; display:flex; justify-content:center; align-items:center; min-height:100vh; margin:0; background:#f0f2f5;}
                        .container{ background:white; padding:30px; border-radius:8px; box-shadow:0 2px 10px rgba(0,0,0,0.1); width:90%; max-width:320px;}
                        h2{ text-align:center; color:#333; margin-top:0;}
                        label{ display:block; margin-bottom:5px; color:#666; font-size:14px;}
                        .hint{ font-size:12px; color:#999; margin-bottom:15px; display:block; margin-top:-15px;}
                        input{ width:100%; padding:12px; margin-bottom:20px; border:1px solid #ddd; box-sizing:border-box; border-radius:4px; font-size:16px;}
                        button{ width:100%; padding:12px; background:#0078d4; color:white; border:none; border-radius:4px; cursor:pointer; font-size:16px; transition: background 0.3s;}
                        button:hover{ background:#005a9e; }
                        .footer-links{ text-align:center; margin-top:20px;}
                        .footer-links a{ color:#666; text-decoration:none; font-size:14px;}
                        .footer-links a:hover{ text-decoration:underline;}
                    </style>
                </head>
                <body>
                <div class="container">
                    <h2>系统设置</h2>
                    <form method="post" action="/@settings">
                        <label>用户名</label>
                        <input name="newuser" type="text" value="` + (config.auth.user || "") + `" required>
                        <label>新密码</label>
                        <input name="newpwd" type="password" placeholder="填写新密码" required>
                        <label>服务端口</label>
                        <input name="newport" type="number" value="` + (config.auth.port : "") + `" placeholder="留空则使用随机端口" min="0" max="65535">
                        <span class="hint">范围: 1-65535。留空或设为 0 则由系统随机分配。</span>
                        <button type="submit">保存修改</button>
                    </form>
                    <div class="footer-links">
                        <a href="/">← 返回首页</a>
                    </div>
                </div>
                </body></html>
                `);
                return;
            }
            case "/@printscreen" {
                var bmp = gdip.snap(); 
                if(bmp){
                    var buf = bmp.saveToBuffer("*.jpg", 80);
                    bmp.dispose();
                    if(buf){
                        response.contentType = "image/jpeg";
                        response.write(buf);
                        return; 
                    }
                }
                response.errorStatus(500, "截图失败");
            }
            case "/@lockpc" {
                ::User32.LockWorkStation();
                response.write(msgPage("指令已发送", ("锁定屏幕"), false));
                return;
            }
            case "/@reboot" {
                if (request.query("confirm") == "1") {
                    winform.edit.print(tostring(time()), request.remoteAddr, user,"确认执行重启指令");
                    raw.execute("shutdown.exe", "-r -f -t 0", "", 0/*_SW_HIDE*/);
                    response.write(msgPage("指令已发送", "计算机正在重启...", false));
                    return;
                }
                response.write(confirmPage("确认重启", "您确定要重启这台计算机吗?未保存的工作将会丢失。", "/@reboot", "确认重启"));
                return;
            }
            case "/@poweroff" {
                if (request.query("confirm") == "1") {
                    winform.edit.print(tostring(time()), request.remoteAddr, user,"确认执行关机指令");
                    raw.execute("shutdown.exe", "-s -f -t 0", "", 0/*_SW_HIDE*/);
                    response.write(msgPage("指令已发送", "计算机正在关机...", false));
                    return;
                }
                response.write(confirmPage("确认关机", "您确定要关闭这台计算机吗?未保存的工作将会丢失。", "/@poweroff", "确认关机"));
                return;
            }
        }
        var dynamicButtons = "";

        for(name, cfg in config.commands){
            if( type(cfg) == "table" && !string.startsWith(name,"_") && name != "save" ){
                var title = cfg.title || name;
                dynamicButtons += `<a href="/` + name + `" class="btn">` + title + `</a>`;
            }
        }

        response.write(`
        <!DOCTYPE html>
        <html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>
                body { display:flex; flex-direction:column; align-items:center; padding:20px; background:#f5f5f5; font-family:sans-serif;}
                .btn { display:block; margin:10px 0; padding:15px; background:#0078d4; color:white; text-decoration:none; text-align:center; width:90%; max-width:300px; border-radius:8px; font-size:18px;}
                .btn-sys { display:block; margin:10px 0; padding:15px; background:#50677a; color:white; text-decoration:none; text-align:center; width:90%; max-width:300px; border-radius:8px; font-size:18px;}
                .logout { color:#666; margin-top:20px; font-size:14px; text-decoration:none;}
                hr { width:100%; border:0; border-top:1px solid #ddd; margin:20px 0; }
        </style></head><body>
            <h3>Web控制台</h3>
            <!-- 插入动态生成的按钮 -->
            ` + dynamicButtons + `
            <a href="/@printscreen" target="_blank" class="btn-sys">屏幕截图</a>
            <a href="/@lockpc" class="btn-sys">锁定屏幕</a>
            <a href="/@reboot" class="btn-sys">重启电脑</a>
            <a href="/@poweroff" class="btn-sys">关闭电脑</a>
            <hr>
            <a href="/@settings" class="logout">系统设置</a>
            <a href="/logout" class="logout">退出登录</a>
        </body></html>
        `);
    }
);

if (config.auth.port){
        server.start("0.0.0.0", config.auth.port);
}
else{
        server.start();
}

winform.edit.print(tostring(time()), "web控制台已启动: ", server.getUrl());
if (initialization = true){
        winform.edit.print(tostring(time()), "程序初始化成功", "默认账号密码:admin/123456");
        winform.show();win.setForeground(winform.hwnd);win.show(winform.hwnd, 0x9/*_SW_RESTORE*/); 
}

win.loopMessage();

WebConsole_web控制台.rar

580.74 KB, 下载次数: 27, 下载积分: 吾爱币 -2 CB

免费评分

参与人数 6吾爱币 +12 热心值 +6 收起 理由
bqi153 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
yxldh + 1 + 1 谢谢@Thanks!
hnhua + 1 + 1 谢谢@Thanks!
★天若有情★ + 1 + 1 我很赞同!
zhangwei6929 + 1 + 1 谢谢@Thanks!
风之暇想 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
BG8HVH 发表于 2026-1-27 21:38
下载下来看看
3#
mimiwuqi 发表于 2026-1-28 16:13
4#
 楼主| alomoi 发表于 2026-1-28 16:33 |楼主
mimiwuqi 发表于 2026-1-28 16:13
需要在同一个局域网吧。。。

对,需要公网访问可以端口映射或者内网穿透
安全起见不建议直接暴漏公网,我自己用的frp的stcp穿透
5#
lee981 发表于 2026-1-28 16:40
厉害厉害,很厉害,收藏了
6#
hnhua 发表于 2026-1-28 23:35
刚好需要一个这样的工具,就碰到了
7#
XMRXI 发表于 2026-1-31 23:18
跟绿色版的远控软件对比的话有什么优势吗?
8#
xjlyg 发表于 2026-2-1 12:06
感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-2-1 18:05

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表