c# 远程网络唤醒电脑(电脑远程开机+内网MAC和IP扫描)(附带源码+主板和Windows开启详细说明+外网远程唤醒方案)

时间:2022-10-21 07:57:04

一、需求

1、人在公司坐,昨晚写的文档放在家中电脑忘记Copy了,想要访问家中电脑拿到文档。

2、家中或公司中局域网内有某台电脑(或服务器)要开机,或者批量一键打开局域网内某些电脑

二、必备条件

1、网线连接电脑网口(wifi无线网卡无法网络唤醒)

2、网卡支持网络唤醒功能

三、设置

1、主板BIOS设置

目前测试过的主板:微星PRO Z690-A WIFI DDR4(MS-7D25)、技嘉B75M-D3V、技嘉B85M-D2V

下面以微星PRO Z690-A为例。

主板:微星PRO Z690-A WIFI DDR4

系统:Windows10

路由器:中兴AX5400,TPLink5600和7660

发包程序:C#,下面有源码,或者伸手党可以直接从下载链接获取发布好的应用程序

 开机狂按Del键进入微星BIOS,其他品牌DEL, ESC, F1, F2, F8, F9, F10, F12

  1. 高级–整合周边设备–网卡ROM启动,设置为允许
  2. 高级–电源管理设置–Eup 2013,设置为禁止
  3. 高级–唤醒事件设置–PCIE设备唤醒,设置为允许

2、网卡(Windows)设置

  1. 控制面板–所有控制面板项–网络连接
  2. 在网卡适配器点击鼠标右键–属性,弹出的属性对话框中
  3. 选择网络选项卡–配置
  4. 选择高级选项卡,将关机 网络唤醒设置为开启,将魔术封包唤醒设置为开启
  5. 电源管理选项卡,勾选下面三个选项,允许此设备唤醒计算机。
  6. 切换为电源管理选项,勾选允许此设备唤醒计算机。
  7. 关闭快速启动,右击开始按钮,点击“电源选项”,点击“选择电源按钮的功能”;点击“更改当前不可用的设置”,把“启用快速启动”勾选。(这条必须做

 

c# 远程网络唤醒电脑(电脑远程开机+内网MAC和IP扫描)(附带源码+主板和Windows开启详细说明+外网远程唤醒方案)

 

c# 远程网络唤醒电脑(电脑远程开机+内网MAC和IP扫描)(附带源码+主板和Windows开启详细说明+外网远程唤醒方案)

 

c# 远程网络唤醒电脑(电脑远程开机+内网MAC和IP扫描)(附带源码+主板和Windows开启详细说明+外网远程唤醒方案)

 3、后记

  1. 电脑网线连接网口处,电脑关机状态下有的会有黄灯常量,有的电脑不亮,都能唤醒
  2. 在设置网卡的时候发现没有关机 网络唤醒的选项的时候,有可能是网卡驱动或者网卡版本不同,没有此选项也能唤醒。

三、C#源码 

伸手党可以直接从下载链接获取发布好的应用程序,下载地址:

https://download.csdn.net/download/hwt0101/86781647

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RemotePowerOn
{
    public partial class Form1 : Form
    {
        //通过正则表达式设定MAC地址筛选标准,关于正则表达式请自行百度
        const string macCheckRegexString = @"^([0-9a-fA-F]{2})(([/\s:-][0-9a-fA-F]{2}){5})$";

        private static readonly Regex MacCheckRegex = new Regex(macCheckRegexString);
        public Form1()
        {
            InitializeComponent();
        }
        public static bool WakeUp(string mac)
        {
            //查看该MAC地址是否匹配正则表达式定义,(mac,0)前一个参数是指mac地址,后一个是从指定位置开始查询,0即从头开始
            if (MacCheckRegex.IsMatch(mac, 0))
            {
                byte[] macByte = FormatMac(mac);
                WakeUpCore(macByte);
                return true;
            }

            return false;

        }

        private static void WakeUpCore(byte[] mac)
        {
            //发送方法是通过UDP
            UdpClient client = new UdpClient();
            //Broadcast内容为:255,255,255,255.广播形式,所以不需要IP
            client.Connect(System.Net.IPAddress.Broadcast, 40000);
            //下方为发送内容的编制,6遍“FF”+17遍mac的byte类型字节。
            byte[] packet = new byte[17 * 6];
            for (int i = 0; i < 6; i++)
                packet[i] = 0xFF;
            for (int i = 1; i <= 16; i++)
                for (int j = 0; j < 6; j++)
                    packet[i * 6 + j] = mac[j];
            //唤醒动作
            int result = client.Send(packet, packet.Length);
        }

        private static byte[] FormatMac(string macInput)
        {
            byte[] mac = new byte[6];

            string str = macInput;
            //消除MAC地址中的“-”符号
            string[] sArray = str.Split('-');


            //mac地址从string转换成byte
            for (var i = 0; i < 6; i++)
            {
                var byteValue = Convert.ToByte(sArray[i], 16);
                mac[i] = byteValue;
            }

            return mac;
        }
        private void button1_Click(object sender, EventArgs e)
        {
            string mac = textBox1.Text;
            WakeUp(mac);
            //WakeUp("25-D5-47-12-97-E2"); 
        }


        private void button2_Click(object sender, EventArgs e)
        {
            #region 方法1

            // TODO: Implement Functionality Here
            // Get my PC IP address
            Msg(string.Format("My IP : {0}", GetIPAddress()));
            // Get My PC MAC address
            Msg(string.Format("My MAC: {0}", GetMacAddress()));
            // Get My PC HostName
            Msg(string.Format("My HostName: {0}", Dns.GetHostName()));
            // Get all devices on network
            Dictionary<IPAddress, PhysicalAddress> all = GetAllDevicesOnLAN();
            foreach (KeyValuePair<IPAddress, PhysicalAddress> kvp in all)
            {
                Msg(string.Format("IP : {0}\n MAC {1}", kvp.Key, kvp.Value));
            }

            #endregion

            #region 方法2
            //GetIPAddress2();
            //foreach (var ip in ips)
            //{
            //    //Console.WriteLine(ip);
            //    Msg(ip);
            //}
            #endregion
        }

        #region MAC扫描方法1
        //public static void Main(string[] args)
        //{
        //	Console.WriteLine("Hello World!");

        //	// TODO: Implement Functionality Here
        //	// Get my PC IP address
        //	Console.WriteLine("My IP : {0}", GetIPAddress());
        //	// Get My PC MAC address
        //	Console.WriteLine("My MAC: {0}", GetMacAddress());
        //	// Get My PC HostName
        //	Console.WriteLine("My HostName: {0}", Dns.GetHostName());
        //	// Get all devices on network
        //	Dictionary<IPAddress, PhysicalAddress> all = GetAllDevicesOnLAN();
        //	foreach (KeyValuePair<IPAddress, PhysicalAddress> kvp in all)
        //	{
        //		Console.WriteLine("IP : {0}\n MAC {1}", kvp.Key, kvp.Value);
        //	}

        //	Console.Write("Press any key to continue . . . ");
        //	Console.ReadKey(true);
        //}

        /// <summary>
        /// MIB_IPNETROW structure returned by GetIpNetTable
        /// DO NOT MODIFY THIS STRUCTURE.
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        struct MIB_IPNETROW
        {
            [MarshalAs(UnmanagedType.U4)]
            public int dwIndex;
            [MarshalAs(UnmanagedType.U4)]
            public int dwPhysAddrLen;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac0;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac1;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac2;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac3;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac4;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac5;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac6;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac7;
            [MarshalAs(UnmanagedType.U4)]
            public int dwAddr;
            [MarshalAs(UnmanagedType.U4)]
            public int dwType;
        }

        /// <summary>
        /// GetIpNetTable external method
        /// </summary>
        /// <param name="pIpNetTable"></param>
        /// <param name="pdwSize"></param>
        /// <param name="bOrder"></param>
        /// <returns></returns>
        [DllImport("IpHlpApi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        static extern int GetIpNetTable(IntPtr pIpNetTable,
                                        [MarshalAs(UnmanagedType.U4)] ref int pdwSize, bool bOrder);

        /// <summary>
        /// Error codes GetIpNetTable returns that we recognise
        /// </summary>
        const int ERROR_INSUFFICIENT_BUFFER = 122;
        /// <summary>
        /// Get the IP and MAC addresses of all known devices on the LAN
        /// </summary>
        /// <remarks>
        /// 1) This table is not updated often - it can take some human-scale time
        ///    to notice that a device has dropped off the network, or a new device
        ///    has connected.
        /// 2) This discards non-local devices if they are found - these are multicast
        ///    and can be discarded by IP address range.
        /// </remarks>
        /// <returns></returns>
        private static Dictionary<IPAddress, PhysicalAddress> GetAllDevicesOnLAN()
        {
            Dictionary<IPAddress, PhysicalAddress> all = new Dictionary<IPAddress, PhysicalAddress>();
            // Add this PC to the list...
            all.Add(GetIPAddress(), GetMacAddress());
            int spaceForNetTable = 0;
            // Get the space needed
            // We do that by requesting the table, but not giving any space at all.
            // The return value will tell us how much we actually need.
            GetIpNetTable(IntPtr.Zero, ref spaceForNetTable, false);
            // Allocate the space
            // We use a try-finally block to ensure release.
            IntPtr rawTable = IntPtr.Zero;
            try
            {
                rawTable = Marshal.AllocCoTaskMem(spaceForNetTable);
                // Get the actual data
                int errorCode = GetIpNetTable(rawTable, ref spaceForNetTable, false);
                if (errorCode != 0)
                {
                    // Failed for some reason - can do no more here.
                    throw new Exception(string.Format(
                        "Unable to retrieve network table. Error code {0}", errorCode));
                }
                // Get the rows count
                int rowsCount = Marshal.ReadInt32(rawTable);
                IntPtr currentBuffer = new IntPtr(rawTable.ToInt64() + Marshal.SizeOf(typeof(Int32)));
                // Convert the raw table to individual entries
                MIB_IPNETROW[] rows = new MIB_IPNETROW[rowsCount];
                for (int index = 0; index < rowsCount; index++)
                {
                    rows[index] = (MIB_IPNETROW)Marshal.PtrToStructure(new IntPtr(currentBuffer.ToInt64() +
                                                                                  (index * Marshal.SizeOf(typeof(MIB_IPNETROW)))
                                                                                 ),
                                                                       typeof(MIB_IPNETROW));
                }
                // Define the dummy entries list (we can discard these)
                PhysicalAddress virtualMAC = new PhysicalAddress(new byte[] { 0, 0, 0, 0, 0, 0 });
                PhysicalAddress broadcastMAC = new PhysicalAddress(new byte[] { 255, 255, 255, 255, 255, 255 });
                foreach (MIB_IPNETROW row in rows)
                {
                    IPAddress ip = new IPAddress(BitConverter.GetBytes(row.dwAddr));
                    byte[] rawMAC = new byte[] { row.mac0, row.mac1, row.mac2, row.mac3, row.mac4, row.mac5 };
                    PhysicalAddress pa = new PhysicalAddress(rawMAC);
                    if (!pa.Equals(virtualMAC) && !pa.Equals(broadcastMAC) && !IsMulticast(ip))
                    {
                        //Console.WriteLine("IP: {0}\t\tMAC: {1}", ip.ToString(), pa.ToString());
                        if (!all.ContainsKey(ip))
                        {
                            all.Add(ip, pa);
                        }
                    }
                }
            }
            finally
            {
                // Release the memory.
                Marshal.FreeCoTaskMem(rawTable);
            }
            return all;
        }

        /// <summary>
        /// Gets the IP address of the current PC
        /// </summary>
        /// <returns></returns>
        private static IPAddress GetIPAddress()
        {
            String strHostName = Dns.GetHostName();
            IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
            IPAddress[] addr = ipEntry.AddressList;
            foreach (IPAddress ip in addr)
            {
                if (!ip.IsIPv6LinkLocal)
                {
                    return (ip);
                }
            }
            return addr.Length > 0 ? addr[0] : null;
        }

        /// <summary>
        /// Gets the MAC address of the current PC.
        /// </summary>
        /// <returns></returns>
        private static PhysicalAddress GetMacAddress()
        {
            foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
            {
                // Only consider Ethernet network interfaces
                if (nic.NetworkInterfaceType == NetworkInterfaceType.Ethernet &&
                    nic.OperationalStatus == OperationalStatus.Up)
                {
                    return nic.GetPhysicalAddress();
                }
            }
            return null;
        }

        /// <summary>
        /// Returns true if the specified IP address is a multicast address
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        private static bool IsMulticast(IPAddress ip)
        {
            bool result = true;
            if (!ip.IsIPv6Multicast)
            {
                byte highIP = ip.GetAddressBytes()[0];
                if (highIP < 224 || highIP > 239)
                {
                    result = false;
                }
            }
            return result;
        }

        #endregion

        #region MAC扫描方法2



        static List<string> ips = new List<string>();
        static Dictionary<string, string> dic1 = new Dictionary<string, string>();

        static void GetIPAddress2()
        {
            string myHostName = Dns.GetHostName();//本机名
            string myHostIP = Dns.GetHostEntry(myHostName).AddressList[1].ToString();//本机IP地址
            string IpRange = myHostIP.Remove(myHostIP.LastIndexOf('.'));//IP网段
            for (int r = 1; r <= 255; r++)//枚举网段计算机
            {
                Ping ping = new Ping();
                ping.PingCompleted += new PingCompletedEventHandler(ping_Completed);//事件绑定方法
                string pingIP = IpRange + "." + r.ToString();
                ping.SendAsync(pingIP, 1000, null);
            }
        }

        static void ping_Completed(object sender, PingCompletedEventArgs e)
        {
            if (e.Reply.Status == IPStatus.Success)
            {
                ips.Add(e.Reply.Address.ToString());
                if (!dic1.ContainsKey(e.Reply.Address.ToString()))
                {
                    dic1[e.Reply.Address.ToString()] = "";
                }
            }
        }

        #endregion



        private void Msg(string e)
        {
            try
            {
                string msg = "";
                //if (string.IsNullOrEmpty(richTextBox1.Text))
                //{
                //    msg = e;
                //}
                //else
                //{
                //    msg = richTextBox1.Text + "\r\n" + e;
                //}
                msg = e;
                if (base.InvokeRequired)
                {
                    base.Invoke(new MethodInvoker(() =>
                    {
                        richTextBox1.Text = richTextBox1.Text + "\r\n" + e;
                    }));
                }
                else
                {
                    richTextBox1.Text = richTextBox1.Text + "\r\n" + e;
                }
            }
            catch
            {
            }
        }

    }
}

四、 外网远程唤醒方案

  1. 家中放一台微型迷你低功耗计算机或者网关(树莓派、网关、迷你服务器)功耗在10W左右,保持24小时常开,一年电费在一百左右。安装向日葵或者ToDesk设置无人值守,支持电脑和手机App连接。随时随地连接到桌面后,用远程发包软件(文中源码或直接下载打包程序)来远程网络唤醒局域网内其他电脑。
  2. 使用向日葵开机棒,参照官方设置即可,主要是开机棒开放了mac地址开机。可以使得开机棒不局限于一台计算机开机了。在向日葵的网站上找到开机棒,或者在手机就app中找到,然后输入mac地址,即可。
  3. 使用路由器(例如TP-Link)自带的域名解析功能,参考文章:【超详细】Windows设置远程唤醒WOL+远程连接(远程开机)_wyouzhi@yyds的博客-CSDN博客_远程开机与远程唤醒bios设置