Удаленное включение по Mac-адресу C# (Wake On Lan)

от автора

В этой статье я хотел бы поделиться небольшим опытом удаленного включения компьютера. Эта тема, пожалуй, многим известна, но хотелось бы еще раз уделить внимание данной технологии. Свою статью я разделю на две части:

  • Сканирование локальной сети, получение IP-адреса, HostName, Mac-address;
  • Создание "magic packet" и отправка.

Вот так примерно выглядит созданная программа:

Итак, приступим к выполнению первого пункта.

1. Сканирование локальной сети: получение IP-адреса, HostName, Mac-address

В настоящее время существует множество программ, которые реализуют данный пункт. В этой статье я напишу пример кода, который будет выполнять поставленную задачу.

Создадим новый проект в Visual Studio WPF C#. Для начала создадим основной элемент- это ListView, где будет выводится полученная информация.

Код XAML

 <ListView Margin="12,84,12,12" Name="listView1">             <ListView.ContextMenu>                 <ContextMenu >                     <MenuItem Header="Копировать">                         <MenuItem Header="IP-adress" Name="copyIP" Click="copyIP_Click" />                         <MenuItem Header="HostName" Name="copyName" Click="copyName_Click" />                         <MenuItem Header="Mac-adress" Name="copyMacAddress" Click="copyMacAddress_Click" />                     </MenuItem>                     <MenuItem Header="Очистить список" Name="ClearList" Click="ClearList_Click" />                     <MenuItem Header="Сохранить список"/>                     <MenuItem Header="Действия">                         <MenuItem Header="Удаленное включение" Name="PowerOn" Click="PowerOn_Click" />                         <MenuItem Header="Удаленное завершение" IsEnabled="False" />                     </MenuItem>                     <MenuItem Header="Отмена"/>                 </ContextMenu>             </ListView.ContextMenu>             <ListView.View>                 <GridView>                     <GridView.Columns>                         <GridViewColumn Header="IP-Адрес" DisplayMemberBinding="{Binding Path=ipAdress}" Width="200"></GridViewColumn>                         <GridViewColumn Header="HostName" DisplayMemberBinding="{Binding Path=nameComputer}" Width="250"></GridViewColumn>                         <GridViewColumn Header="Mac адрес" DisplayMemberBinding="{Binding Path=MacAdress}" Width="250"></GridViewColumn>                     </GridView.Columns>                 </GridView>             </ListView.View>         </ListView> 

Код C#

 class TableHost     {         public string ipAdress { get; set; }         public string nameComputer { get; set; }         public string MacAdress { get; set; }     } 

Следующим действием узнаем свой IP-адрес и приступим к сканировании локальной сети. Код простой, даже для новичка он не вызовет особых трудностей.

Код C#

 // Получение ip-адреса.             System.Net.IPAddress ip = System.Net.Dns.GetHostByName(host).AddressList[0];   private void button2_Click(object sender, RoutedEventArgs e)         {             int i = int.Parse(ipToString[0]);             int j = int.Parse(ipToString[1]);                 {                     for(int k = 0;k<6;k++)                     {                         for (int m = 0; m < 254; m++)                         {                              //Запускаем проверку в новом потоке                             Thread _thread = new Thread(() => GetInform(string.Format("{0}.{1}.{2}.{3}", i.ToString(), j.ToString(), k.ToString(), m.ToString())));                             _thread.Start();                                                     }                     }                 }                         }  private void GetInform(string textName)         {             string IP_Address = "";             string HostName = "";             string MacAddress = "";              try             {                 //Проверяем существует ли IP                 entry = Dns.GetHostEntry(textName);                 foreach (IPAddress a in entry.AddressList)                 {                     IP_Address = a.ToString();                     break;                 }                  //Получаем HostName                 HostName = entry.HostName;                  //Получаем Mac-address                 IPAddress dst = IPAddress.Parse(textName);                   byte[] macAddr = new byte[6];                 uint macAddrLen = (uint)macAddr.Length;                  if (SendARP(BitConverter.ToInt32(dst.GetAddressBytes(), 0), 0, macAddr, ref macAddrLen) != 0)                     throw new InvalidOperationException("SendARP failed.");                  string[] str = new string[(int)macAddrLen];                 for (int i = 0; i < macAddrLen; i++)                     str[i] = macAddr[i].ToString("x2");                  MacAddress = string.Join(":", str);                  //Далее, если всё успешно, добавляем все данные в список, после чего выводим всё в ListView                 Dispatcher.Invoke(new Action(() =>                 {                      _host.Add(new TableHost() { ipAdress = IP_Address, nameComputer = HostName, MacAdress = MacAddress });                     listView1.ItemsSource = null;                     listView1.ItemsSource = _host;                 }));             }             catch { }                     } 

Теперь мы имеем всё, что нам необходимо. Приступаем к следующему этапу.

2. Создание «magic packet» и отправка

С определением вы можете ознакомится здесь. Этот этап, как вы сами понимаете, будет работать только с выключенным компьютером, так что нам необходимо будет сохранить всю информацию. Полный код я напишу в конце статьи.

Код на самом деле не такой то уж и страшный, деятельность этого пункта можно разделить на два этапа: создание пакета и его отправка.

Код C#

        [DllImport("iphlpapi.dll", ExactSpelling = true)]         public static extern int SendARP(int destIp, int srcIP, byte[] macAddr, ref uint physicalAddrLen); private void WakeFunction(string MAC_ADDRESS)         {             WOLClass client = new WOLClass();             client.Connect(new IPAddress(0xffffffff), 0x2fff);             client.SetClientToBrodcastMode();             int counter = 0;             //буфер для отправки             byte[] bytes = new byte[1024];             //Первые 6 бит 0xFF             for (int y = 0; y < 6; y++)                 bytes[counter++] = 0xFF;             //Повторим MAC адрес 16 раз             for (int y = 0; y < 16; y++)             {                 int i = 0;                 for (int z = 0; z < 6; z++)                 {                     bytes[counter++] = byte.Parse(MAC_ADDRESS.Substring(i, 2), NumberStyles.HexNumber);                     i += 2;                 }             }              //Отправляем полученный магический пакет             int reterned_value = client.Send(bytes, 1024);         }  public class WOLClass : UdpClient     {         public WOLClass()             : base()         { }         //Установим broadcast для отправки сообщений         public void SetClientToBrodcastMode()         {             if (this.Active)                 this.Client.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.Broadcast, 0);         }     } 

Вот, наверное, и всё, я постарался пробежаться по основным моментам несложной, но очень интересной программы. Для статьи я наполнил эту программу еще некоторым функционалом, чтобы как-то разнообразить ее. Если кого то заинтересует — здесь есть, что взять для себя. Ниже представлен весь код:

Код XAML

<Window x:Class="Network.MainWindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         Title="MainWindow" Height="497" Width="872" Closing="Window_Closing">     <Grid>         <ListView Margin="12,84,12,12" Name="listView1">             <ListView.ContextMenu>                 <ContextMenu >                     <MenuItem Header="Копировать">                         <MenuItem Header="IP-adress" Name="copyIP" Click="copyIP_Click" />                         <MenuItem Header="HostName" Name="copyName" Click="copyName_Click" />                         <MenuItem Header="Mac-adress" Name="copyMacAddress" Click="copyMacAddress_Click" />                     </MenuItem>                     <MenuItem Header="Очистисть список" Name="ClearList" Click="ClearList_Click" />                     <MenuItem Header="Сохранить список"/>                     <MenuItem Header="Действия">                         <MenuItem Header="Удаленное включение" Name="PowerOn" Click="PowerOn_Click" />                         <MenuItem Header="Удаленное завершение" IsEnabled="False" />                     </MenuItem>                     <MenuItem Header="Отмена"/>                 </ContextMenu>             </ListView.ContextMenu>             <ListView.View>                 <GridView>                     <GridView.Columns>                         <GridViewColumn Header="IP-Адрес" DisplayMemberBinding="{Binding Path=ipAdress}" Width="200"></GridViewColumn>                         <GridViewColumn Header="HostName" DisplayMemberBinding="{Binding Path=nameComputer}" Width="250"></GridViewColumn>                         <GridViewColumn Header="Mac адрес" DisplayMemberBinding="{Binding Path=MacAdress}" Width="250"></GridViewColumn>                     </GridView.Columns>                 </GridView>             </ListView.View>         </ListView>         <TextBox Height="23" HorizontalAlignment="Left" Margin="221,15,0,0" Name="textBox1" VerticalAlignment="Top" Width="164" />         <Label  Height="27" HorizontalAlignment="Left" Margin="219,36,0,0" Name="label1" VerticalAlignment="Top" Width="316">             IP-адресс/Host-имя компьютера,                              например: 192.168.1.1         </Label>         <Button Content="Начать сканирование" Height="52" HorizontalAlignment="Left" Margin="12,15,0,0" Name="button2" VerticalAlignment="Top" Width="153" Click="button2_Click" />         <Label Content="Ваш IP:" Height="28" HorizontalAlignment="Right" Margin="0,1,125,0" Name="label2" VerticalAlignment="Top" Width="50" />         <Label Height="28" Margin="0,1,2,0" Name="label3" VerticalAlignment="Top" HorizontalAlignment="Right" Width="117" />         <Button Content="Проверить" Height="23" HorizontalAlignment="Left" Margin="415,15,0,0" Name="button1" VerticalAlignment="Top" Width="120" Click="button1_Click_1" />         <ComboBox Height="23" HorizontalAlignment="Right" Margin="0,45,62,0" Name="comboBox1" VerticalAlignment="Top" Width="199" SelectionChanged="comboBox1_SelectionChanged" />         <Grid Background="#FF9D9D9D" HorizontalAlignment="Right" Margin="0,91,-191,10" Name="rectangle1" Width="178">             <Label Content="IP- адрес" Height="28" Margin="16,25,23,0" Name="label4" VerticalAlignment="Top" />             <TextBox Height="23" HorizontalAlignment="Left" Margin="16,53,0,0" Name="textBox2" VerticalAlignment="Top" Width="139" />             <TextBox Height="23" HorizontalAlignment="Left" Margin="16,124,0,0" Name="textBox3" VerticalAlignment="Top" Width="139" />             <Label Content="HostName" Height="28" Margin="16,90,23,0" Name="label5" VerticalAlignment="Top" />             <TextBox Height="23" HorizontalAlignment="Left" Margin="16,203,0,0" Name="textBox4" VerticalAlignment="Top" Width="139" />             <Label Content="Mac-address" Height="28" Margin="16,169,23,0" Name="label6" VerticalAlignment="Top" />             <Button Content="Включить" Height="23" HorizontalAlignment="Left" Margin="16,0,0,58" Name="button3" VerticalAlignment="Bottom" Width="139" Click="button3_Click" />             <Button Content="Закрыть" Height="23" HorizontalAlignment="Left" Margin="16,0,0,19" Name="button4" VerticalAlignment="Bottom" Width="139" Click="button4_Click" />         </Grid>     </Grid> </Window>  

код C#

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Net; using System.Runtime.InteropServices; using System.Threading; using System.Net.Sockets; using System.Globalization; using System.IO;  namespace Network {     /// <summary>     /// Interaction logic for MainWindow.xaml     /// </summary>     public partial class MainWindow : Window     {         [DllImport("iphlpapi.dll", ExactSpelling = true)]         public static extern int SendARP(int destIp, int srcIP, byte[] macAddr, ref uint physicalAddrLen);          List<TableHost> _host = new List<TableHost>();         string hostname = "";         IPHostEntry entry ;         string[] ipToString = new string[4];           public MainWindow()         {             InitializeComponent();                              //string[] first = adress.ToString().Split('.');                 //string[] second = IPAddress.Parse("192.168.1.0").ToString().Split('.');             // Получение имени компьютера.             String host = System.Net.Dns.GetHostName();             // Получение ip-адреса.             System.Net.IPAddress ip = System.Net.Dns.GetHostByName(host).AddressList[0];             // Показ адреса в label'е.             label3.Content = ip.ToString();             ipToString = ip.ToString().Split('.');             ADd();         }          string[] ipadressText;         string[] hostnameText;         string[] macaddressText;          private void ADd()         {             string[] str = File.ReadAllLines("IPMAC.txt");             ipadressText = new string[str.Length];             hostnameText = new string[str.Length];             macaddressText = new string[str.Length];             for (int i = 0; i < str.Length; i++)             {                 string[] s = str[i].Split('#');                 ipadressText[i] = s[0];                 hostnameText[i] = s[1];                 macaddressText[i] = s[2];                 comboBox1.Items.Add(s[1]);             }                      }          private void WakeFunction(string MAC_ADDRESS)         {             WOLClass client = new WOLClass();             client.Connect(new IPAddress(0xffffffff), 0x2fff);             client.SetClientToBrodcastMode();             int counter = 0;             //буффер для отправки             byte[] bytes = new byte[1024];             //Первые 6 бит 0xFF             for (int y = 0; y < 6; y++)                 bytes[counter++] = 0xFF;             //Повторим MAC адрес 16 раз             for (int y = 0; y < 16; y++)             {                 int i = 0;                 for (int z = 0; z < 6; z++)                 {                     bytes[counter++] = byte.Parse(MAC_ADDRESS.Substring(i, 2), NumberStyles.HexNumber);                     i += 2;                 }             }              //Отправляем полученый магический пакет             int reterned_value = client.Send(bytes, 1024);         }           private void GetInform(string textName)         {             string IP_Address = "";             string HostName = "";             string MacAddress = "";              try             {                 //Проверяем существует ли IP                 entry = Dns.GetHostEntry(textName);                 foreach (IPAddress a in entry.AddressList)                 {                     IP_Address = a.ToString();                     break;                 }                  //Получаем HostName                 HostName = entry.HostName;                  //Получаем Mac-address                 IPAddress dst = IPAddress.Parse(textName);                   byte[] macAddr = new byte[6];                 uint macAddrLen = (uint)macAddr.Length;                  if (SendARP(BitConverter.ToInt32(dst.GetAddressBytes(), 0), 0, macAddr, ref macAddrLen) != 0)                     throw new InvalidOperationException("SendARP failed.");                  string[] str = new string[(int)macAddrLen];                 for (int i = 0; i < macAddrLen; i++)                     str[i] = macAddr[i].ToString("x2");                  MacAddress = string.Join(":", str);                  //Далее, если всё успешно, добавляем все данные в список, после чего выводим всё в ListView                 Dispatcher.Invoke(new Action(() =>                 {                      _host.Add(new TableHost() { ipAdress = IP_Address, nameComputer = HostName, MacAdress = MacAddress });                     listView1.ItemsSource = null;                     listView1.ItemsSource = _host;                 }));             }             catch { }                     }           private void button1_Click(object sender, RoutedEventArgs e)         {              //string message = "";             //Print(GetIP(textBox1.Text), GetHostName(textBox1.Text), GetMac(message));         }          private void button2_Click(object sender, RoutedEventArgs e)         {             int i = int.Parse(ipToString[0]);             int j = int.Parse(ipToString[1]);                 {                     for(int k = 0;k<6;k++)                     {                         for (int m = 0; m < 254; m++)                         {                             Thread _thread = new Thread(() => GetInform(string.Format("{0}.{1}.{2}.{3}", i.ToString(), j.ToString(), k.ToString(), m.ToString())));                             _thread.Start();                                                     }                     }                 }                         }          private void PowerOn_Click(object sender, RoutedEventArgs e)         {             try             {                 WakeFunction(_host[listView1.SelectedIndex].MacAdress.ToString().Replace(":", ""));                 MessageBox.Show("Операция выполнена успешно!", "Внимание!", MessageBoxButton.OK, MessageBoxImage.Information);             }             catch { MessageBox.Show("Запрос некорретный!","Внимание!Ошибка!",MessageBoxButton.OK,MessageBoxImage.Error); }         }          private void ClearList_Click(object sender, RoutedEventArgs e)         {             _host.Clear();             listView1.Items.Refresh();         }          private void copyIP_Click(object sender, RoutedEventArgs e)         {             Clipboard.SetText(_host[listView1.SelectedIndex].ipAdress.ToString());         }          private void copyName_Click(object sender, RoutedEventArgs e)         {             Clipboard.SetText(_host[listView1.SelectedIndex].nameComputer.ToString());         }          private void copyMacAddress_Click(object sender, RoutedEventArgs e)         {             Clipboard.SetText(_host[listView1.SelectedIndex].MacAdress.ToString());         }          private void button1_Click_1(object sender, RoutedEventArgs e)         {             GetInform(textBox1.Text);         }          private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)         {             StreamWriter write = new StreamWriter(@"C:\Users\***\IPMAC.txt", true);              for (int index = 0; index < _host.Count; index++)             {                  if (!macaddressText.Contains(_host[index].MacAdress))                     write.WriteLine(_host[index].ipAdress + "#" + _host[index].nameComputer + "#" + _host[index].MacAdress);             }             write.Close();         }          void P()         {             for (double i = -192; i < 10; i += 0.004)             {                 Dispatcher.Invoke(new Action(() =>                 {                     rectangle1.Margin = new Thickness(0, 101, i, 10);                 }));              }//12,0,12,1           }          private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)         {             //ii = rectangle1.Width;             textBox2.Text = ipadressText[comboBox1.SelectedIndex];             textBox3.Text = comboBox1.SelectedItem.ToString();             textBox4.Text = macaddressText[comboBox1.SelectedIndex];             Thread thread = new Thread(P);             thread.Start();         }          private void button3_Click(object sender, RoutedEventArgs e)         {             try             {                 WakeFunction(textBox4.Text.Replace(":", ""));                 MessageBox.Show("Операция выполнена успешно!", "Внимание!", MessageBoxButton.OK, MessageBoxImage.Information);             }             catch { MessageBox.Show("Запрос некорретный!", "Внимание!Ошибка!", MessageBoxButton.OK, MessageBoxImage.Error); }         }          private void button4_Click(object sender, RoutedEventArgs e)         {             Thread thread = new Thread(CLose);             thread.Start();         }          void CLose()         {             for (double i = 9; i > -193; i -= 0.004)             {                 Dispatcher.Invoke(new Action(() =>                 {                     rectangle1.Margin = new Thickness(0, 101, i, 10);                 }));              }//12,0,12,1         }     }      class TableHost     {         public string ipAdress { get; set; }         public string nameComputer { get; set; }         public string MacAdress { get; set; }     }      public class WOLClass : UdpClient     {         public WOLClass()             : base()         { }         //Установим broadcast для отправки сообщений         public void SetClientToBrodcastMode()         {             if (this.Active)                 this.Client.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.Broadcast, 0);         }     } }  

ссылка на оригинал статьи http://habrahabr.ru/post/262699/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *