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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM