你的想法很重要-大家都来谈 (C)Copyright 2012 by WeiPt

在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>

 

posted @ 2022-01-04 18:42  weipt  阅读(2548)  评论(5编辑  收藏  举报

你的想法很重要-大家都来谈 (C)Copyright 2012 by WeiPt