zoukankan      html  css  js  c++  java
  • 在web端使用html5访问远程桌面

    前几天看见一篇文章很受启发,通过html5实现远程桌面共享,但是文中给的两段代码实在没有多大用途,

    于是这几天正好西安封城,就研究了一下简单实现了,不过还不太稳定,先发布出来。

    1、原理简介

    服务器端就是被控制的电脑,开启websocket端口监听,可以用封装好的fleck包。

    接收到客户端信息解析键盘和鼠标事件,然后在本机上发送这些键盘和鼠标按键(用现成的组件KeyMouseHook)。

    加个定时器每隔500毫秒执行截屏,并给所有客户端发送。

    2、服务器端代码

    using Fleck;
    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Configuration;
    using System.Data;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using Loamen.KeyMouseHook;
    using Loamen.KeyMouseHook.Native;
    namespace 服务器
    {
        public partial class Form1 : Form
        {
    
            List<IWebSocketConnection> allSockets;
            WebSocketServer server;
            InputSimulator sim = new InputSimulator();
    
    
            [DllImport("user32.dll")]
            public static extern bool PrintWindow(
            IntPtr hwnd,               // Window to copy,Handle to the window that will be copied. 
            IntPtr hdcBlt,             // HDC to print into,Handle to the device context. 
            UInt32 nFlags              // Optional flags,Specifies the drawing options. It can be one of the following values. 
            );
            public Form1()
            {
                InitializeComponent();
            }
    
           
            private void fsAddConsole(string message)
            {
                if (richTextBox1.Text.Length > 50000)
                {
                    richTextBox1.Clear();
                }
                richTextBox1.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));
                richTextBox1.AppendText(" " + message);
                richTextBox1.AppendText("\r\n");
                richTextBox1.ScrollToCaret();
                //写日志
                if (checkBox3.Checked)
                {
                    string path = ConfigurationManager.AppSettings["check_log_path"].ToString() + "/" + DateTime.Now.ToString("yyyy-MM-dd");
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }
                    File.AppendAllText(path + "/wsserver" + "_巡检日志.log", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff") + " " + message + "\r\n", Encoding.UTF8);
                }
                else { 
                }
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                //管理Socket
                allSockets = new List<IWebSocketConnection>();
                //配置地址
                server = new WebSocketServer("ws://" + textBox1.Text + ":" + textBox2.Text);
                //出错后进行重启
                server.RestartAfterListenError = true;
                //开始监听
                server.Start(socket =>
                {
                    //关联连接建立事件
                    socket.OnOpen = () =>
                    {
                        Invoke((new Action(() =>
                        {
                            fsAddConsole("Open!");
                        })));
    
    
                        allSockets.Add(socket);
    
                        //allSockets.ToList().ForEach(
                        //    s => s.Send (ImageToBytes(pictureBox1.Image))
                        //    );
                    };
    
                    //关联连接关闭事件
                    socket.OnClose = () =>
    
                    {
    
    
                        Invoke((new Action(() =>
                        {
                            fsAddConsole("Close!");
                        })));
                        allSockets.Remove(socket);
    
                    };
    
                    //接受客户端消息事件
                    socket.OnMessage = message =>
                    {
                        Invoke((new Action(() =>
                        {
                            fsAddConsole(message);
                            if (checkBox2.Checked)
                            {
                                var cmd = JsonConvert.DeserializeObject<ClientCmd>(message);
                                if (cmd.action == "mousemove")
                                {
                                    var point = new Point(cmd.x, cmd.y).ToAbsolutePoint();
                                    sim.Mouse.MoveMouseTo(point.X, point.Y);
    
                                }
                                else if (cmd.action == "mousedown")
                                {
                                    sim.Mouse.LeftButtonDown();
                                }
                                else if (cmd.action == "mouseup")
                                {
                                    sim.Mouse.LeftButtonUp();
                                }
                                else if (cmd.action == "click")
                                {
                                    sim.Mouse.LeftButtonClick();
    
                                }
                                else if (cmd.action == "dbclick")
                                {
                                    sim.Mouse.LeftButtonDoubleClick();
                                }
                                else if (cmd.action == "rightclick")
                                {
                                     sim.Mouse.RightButtonClick();
                                }
                                else if (cmd.action == "keypress")
                                {
                                    //sim.Keyboard.KeyPress();
                                }
                                else if (cmd.action == "keyup")
                                {
                                    List<VirtualKeyCode> modifiedkey = new List<VirtualKeyCode>();
                                    if (cmd.shift)
                                    {
                                        modifiedkey.Add(VirtualKeyCode.SHIFT);
                                    }
                                    if (cmd.ctrl)
                                    {
                                        modifiedkey.Add(VirtualKeyCode.CONTROL);
                                    }
                                    if (cmd.alt)
                                    {
                                        modifiedkey.Add(VirtualKeyCode.MENU);
                                    }
    
                                    sim.Keyboard.ModifiedKeyStroke(modifiedkey, (VirtualKeyCode)cmd.key);
                                }
                                else
                                {
                                    //其他指令
                                }
                            }
                            else { 
                                //查看模式,不响应远程指令
                            }
                        })));
    
                        //allSockets.ToList().ForEach(
                        //    s => s.Send("bili: " + message));
    
                    };
    
                    //socket.OnPing
    
                });
                fsAddConsole("开始监听");
            }
    
            private void Form1_Shown(object sender, EventArgs e)
            {
                textBox1.Text = ConfigurationManager.AppSettings["ip"].ToString();
                textBox2.Text = ConfigurationManager.AppSettings["port"].ToString();
            }
            Image imgTemp;
            private Image GetWindowImage(IntPtr windownHandle)
            {
                Control control = Control.FromHandle(windownHandle);
                Bitmap image = new Bitmap(control.Width, control.Height);
                Graphics gp = Graphics.FromImage(image);
                IntPtr dc = gp.GetHdc();
                PrintWindow(windownHandle, dc, 0);
                gp.ReleaseHdc();
                gp.Dispose();
                return image;
            }
            private void button2_Click(object sender, EventArgs e)
            {
                try
                {
                   // imgTemp = GetWindowImage(Handle);
                    Bitmap bt = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
                    Graphics g = Graphics.FromImage(bt);
                    g.CopyFromScreen(new Point(0, 0), new Point(0, 0), Screen.PrimaryScreen.Bounds.Size);//获取屏幕截图
                    imgTemp = SaveJpg(bt, 10);//设置图片清晰度
                    //                          //mm = GetWebImage(mm, 360, 240);//改变截屏图片大小
                    //                          //mm.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                    //                          // pictureBox1.Image = tmgTemp;
                   // PrintScreen ps = new PrintScreen();
                    //imgTemp = ps.CaptureScreen();
                    //ps.CaptureScreenToFile(di + $"\\screenShoot{Guid.NewGuid()}.png", ImageFormat.Png);
                    fsAddConsole("获取屏幕成功");
                }
                catch (Exception ex)
                {
                    fsAddConsole("获取屏幕出错"+ex.Message);
                    // throw;
                }
    
    
            }
            public Image SaveJpg(Image image, long value)//设置图像质量1—100
            {
                ImageCodecInfo icInfo = null;
                ImageCodecInfo[] infos = ImageCodecInfo.GetImageEncoders();
                foreach (ImageCodecInfo info in infos)
                {
                    if (info.MimeType == "image/jpeg")
                    {
                        icInfo = info;
                        break;
                    }
                }
                EncoderParameters ep = new EncoderParameters(2);
                ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, value);//质量,定义图片的清晰度
                ep.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionLZW);//压缩,似乎无效果
                return image;
            }
    
            /// <summary>
            /// Convert Image to Byte[]
            /// </summary>
            /// <param name="image"></param>
            /// <returns></returns>
            public byte[] ImageToBytes(Image image)
            {
                MemoryStream ms = new MemoryStream();
                image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                return ms.ToArray();
    
            }
    
    
            private void button3_Click(object sender, EventArgs e)
            {
                allSockets.ToList().ForEach(
                         s => s.Send(ImageToBytes(imgTemp))
                         );
            }
    
            private void button4_Click(object sender, EventArgs e)
            {
                byte[] xx = ImageToBytes(imgTemp);
                MessageBox.Show(xx.Length.ToString()
                    );
            }
    
            private void checkBox1_CheckedChanged(object sender, EventArgs e)
            {
                timer1.Enabled = checkBox1.Checked;
            }
    
            private void timer1_Tick(object sender, EventArgs e)
            {
                button2_Click(sender, e);
                button3_Click(sender, e);
            }
        
    }
    }

    3、服务端界面截图

     不做过多解释,上面的控件名称都是默认的,容易找到。

    4、服务器端其他文件

    还有一个指令类,没啥内容就截图看看

     程序配置文件

     5、客户端是jquery写的

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
        <script src="jquery-1.11.2.min.js"></script>
    
        <style>
          body {
            padding: 0px;
            margin: 0px;
          }
        </style>
      </head>
    
      <body onselectstart="return false" width="100%" height="100%">
        <!-- <img id="desktop" width="100%" height="100%" /> -->
        <canvas id="desktop" width="1200px" height="800px"></canvas>
      </body>
      <script>
        var wsImpl = window.WebSocket || window.MozWebSocket;
        var ws = new wsImpl("ws://127.0.0.1:10086/");
        var _canvas = document.getElementById("desktop");
        var _ctx = _canvas.getContext("2d");
        _canvas.width = window.innerWidth;
        _canvas.height = window.innerHeight;
        var image = new Image();
        ws.onmessage = function (evt) {
          //第一种方法:直接设置图片路径
          // var image = document.getElementById("desktop");
          // image.src = URL.createObjectURL(evt.data) ;
          //第二种方法:设置canvas 通过二进制图片方式
    
          image.src = URL.createObjectURL(evt.data);
          image.onload = function () {
            _ctx.drawImage(image, 0, 0);
            var imagedata = _ctx.getImageData(0, 0, 1200, 1200);
            _ctx.createImageData(imagedata);
          };
          //第三种方法:
          // var imageData = _ctx.createImageData(1200, 800);
          // imageData.data.set(evt.data);
          // _ctx.putImageData(imageData, 0, 0);
        };
    
        // $(window).keypress(function (event) {
        //   //键按下的时候
        // });
    
        var shift_press = "false";
        var ctrl_press = "false";
        var alt_press = "false";
    
        $(window).keydown(function (event) {
          if (event.ctrlKey) {
            ctrl_press = "true";
          } else {
            ctrl_press = "false";
          }
          if (event.shiftKey) {
            shift_press = "true";
          } else {
            shift_press = "false";
          }
          if (event.altKey) {
            alt_press = "true";
          } else {
            alt_press = "false";
          }
          if (event.key != "Shift" && event.key != "Ctrl" && event.key != "Alt") {
            ws.send(
              "{'action':'keydown','key':" +
                event.keyCode +
                ",'shift':" +
                shift_press +
                ",'ctrl':" +
                ctrl_press +
                ",'alt':" +
                alt_press +
                "}"
            );
          }
        });
        $(window).keyup(function (event) {
          if (event.ctrlKey) {
            ctrl_press = "true";
          } else {
            ctrl_press = "false";
          }
          if (event.shiftKey) {
            shift_press = "true";
          } else {
            shift_press = "false";
          }
          if (event.altKey) {
            alt_press = "true";
          } else {
            alt_press = "false";
          }
          if (event.key != "Shift" && event.key != "Ctrl" && event.key != "Alt") {
            ws.send(
              "{'action':'keyup','key':" +
                event.keyCode +
                ",'shift':" +
                shift_press +
                ",'ctrl':" +
                ctrl_press +
                ",'alt':" +
                alt_press +
                "}"
            );
          }
        });
    
        $(desktop).mousemove(function (e) {
          var _x = e.offsetX;
          var _y = e.offsetY;
    
          ws.send("{'action':'mousemove','x':'" + _x + "','y':'" + _y + "'}");
        });
    
        $(desktop).contextmenu(function (e) {
          e.returnValue = false;
          var _x = e.offsetX;
          var _y = e.offsetY;
    
          ws.send("{'action':'rightclick','x':'" + _x + "','y':'" + _y + "'}");
        });
    
        $(desktop).mousedown(function (e) {
          ws.send(
            "{'action':'mousedown','x':'" + e.offsetX + "','y':'" + e.offsetY + "'}"
          );
        });
    
        $(desktop).mouseup(function (e) {
          ws.send(
            "{'action':'mouseup','x':'" + e.offsetX + "','y':'" + e.offsetY + "'}"
          );
        });
    
        $(desktop).click(function (e) {
          ws.send(
            "{'action':'click','x':'" + e.offsetX + "','y':'" + e.offsetY + "'}"
          );
        });
    
        $(desktop).dblclick(function (e) {
          ws.send(
            "{'action':'dbclick','x':'" + e.offsetX + "','y':'" + e.offsetY + "'}"
          );
        });
    
        document.oncontextmenu = function () {
          event.returnValue = false;
        };
      </script>
    </html>
  • 相关阅读:
    数据库锁表处理汇总
    2021,顺其自然
    NetCore中跨域策略的一个坑
    Furion框架亮点之-动态WebAPI
    sql中where in的数量限制
    动态规划学习笔记
    用Go编写Web应用程序
    Asp.net Core AutoFac根据程序集实现依赖注入
    Linux+Docker+Gitee+Jenkins自动化部署.NET Core服务
    CentOS8.0安装Nacos
  • 原文地址:https://www.cnblogs.com/weipt/p/15763626.html
Copyright © 2011-2022 走看看