C#でWake on lanアプリを作成してみた

アプリの使い方

最初に作成したアプリの使い方を説明します。
未署名(野良)アプリとなりますが、サイト内からインストーラもダウンロード可能にしています。
※Windows10以降では危険なアプリとして認識されます。

MACアドレスの取得

Wake on lanしたいPCが起動した状態で、PCに割り当てられたIPアドレスを指定して、MACアドレスを取得しておきます。
この作業は一度行えば、アプリケーション内にMACアドレスが保存されます。

MagicPacketの送信

起動したいPCの電源が切れた状態で、PortとAreaを設定し、"SendMP"ボタンを押すとマジックパケットを送信します。

MACアドレスの取得

Wake on lanはブロードキャストアドレスに対して、NICのMACアドレスを含むパケットを送信します。
そのためにはMACアドレスを取得する機能が必要なので実装しておきます。

Send ARP機能

まずはWake on lanしたいPCを起動した状態で、IPアドレスを指定し、MACアドレスを取得する機能の実装です。
自作でMacAddressクラスを作成しました。

    [DllImport("iphlpapi.dll", ExactSpelling = true)]
    private static extern int SendARP(int DestIP, int SrcIp, byte[] pMacAddr, ref int PhyAddrLen);

    public byte[] macAddr;

    public int macAddrLen;

    public IPAddress ipAddress;

    public MacAddress() 
    {
        macAddr = new byte[6];
        macAddrLen = macAddr.Length;
    }

    public bool SetIpAddr(string ipAddrStr)
    {
        if (IPAddress.TryParse(ipAddrStr, out ipAddress))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public bool TrySendArp()
    {
        int addr = BitConverter.ToInt32(ipAddress.GetAddressBytes(), 0);  //IPv4値を値に変換

        int ret = SendARP(addr, 0, macAddr, ref macAddrLen);

        if (ret == 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

クラスの使用方法は"SetIpAddr"メソッドでIPアドレスを設定し、"TrySendArp"メソッドを実行することでMACアドレスが取得できます。
取得したMACアドレスはbyte配列で取得できます。以下、コード例です。

ボタンクリックイベントでテキストボックスからIPアドレスの文字列データを取得し、MACアドレスを取得します。
取得したMACアドレスをテキストボックスに表示するとともに、ユーザーデータとして保存しています。

private void BtnSendArp_Click(object sender, EventArgs e)
{
    MacAddress macAddress = new MacAddress();
    if (macAddress.SetIpAddr(TbxIpAddress.Text))
    {
        if (macAddress.TrySendArp())
        {
            TbxMacAddress.Text = BitConverter.ToString(macAddress.macAddr);
            Properties.Settings.Default.MacAddress = TbxMacAddress.Text;
            Properties.Settings.Default.Save();
        }
    }
}

事前にMACアドレスを取得しておく

別の方法でMACアドレスが取得できればSend ARP機能は不要ですが、実用的なアプリを作りたかったので、MACアドレス取得機能を実装しました。
実際に使用する場合はWake on lanしたいPCが起動した状態でMACアドレスを取得しておき、ユーザーデータとして保存しておくことで、マジックパケット送信時に使用できます。

マジックパケットの送信

次にマジックパケット送信機能の実装です。
以前作成したUdpClientクラスも流用します。

MagicPacketクラス

UdpClientを使用して任意のネットワークにマジックパケットを送信する機能を持つクラスです。
プロパティの"ipaddress"にはブロードキャストアドレスを登録して、使用します。

internal class MagicPacket
{
    public byte[] macAddress;

    public byte[] broadcastPacket;

    public IPAddress ipaddress;

    public TcpUdpCommunication.UdpClient udpClient;

    public MagicPacket(MacAddress macAddr)
    {
        macAddress = macAddr.macAddr;
    }

    public MagicPacket(byte[] macAddr)
    {
        macAddress = macAddr;
    }

    public MagicPacket()
    {

    }

    public bool SetMacAddress(string macAddrStr)
    {
        try
        {
            PhysicalAddress physicalAddress = PhysicalAddress.Parse(macAddrStr);
            macAddress = physicalAddress.GetAddressBytes();
            return true;
        }
        catch
        {
            return false;
        }
    }

    public void UdpClientInit(string ipAddrStr, int port)
    {
        if (IPAddress.TryParse(ipAddrStr, out IPAddress ipAddress))
        {

        }
        else
        {

        }
        udpClient = new TcpUdpCommunication.UdpClient(ipAddress, port);
    }

    public void SendPacket()
    {
        udpClient.sendData = SetPacket();
        udpClient.ComTaskGen();
    }

    private byte[] SetPacket()
    {
        byte[] packet = new byte[6 + 6 * 16];
        Array.Copy(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, 0, packet, 0, 6);
        for (int i = 1; i <= 16; ++i)
            Array.Copy(macAddress, 0, packet, i * macAddress.Length, macAddress.Length);
        return packet;
    }
}

使用例

まず、"SetMacAddress"メソッドでMACアドレスを登録します。引数として与えるMACアドレスは文字列形式です。
そして、"UdpClientInit"メソッドブロードキャストアドレスとポート番号を与えて準備完了です。
"SendPacket"メソッドを実行するとマジックパケットを送信します。

private void BtnSendMagicPacket_Click(object sender, EventArgs e)
{
    MagicPacket magicPacket = new MagicPacket();
    magicPacket.SetMacAddress(TbxMacAddress.Text);
    if(Int32.TryParse(TbxPort.Text, out int intBuf))
    {
        magicPacket.UdpClientInit(TbxAreaAddress.Text, intBuf);
        magicPacket.SendPacket();
    }
    
}

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

18 − four =