CAD日記

主にAutoCADのことについて書いているけど、近頃は投資系ネタに注力している。自動売買、仮想通貨、PC関係、プログラミングなど。@caddiary

ソフト開発

インフラSEへの道~マジックパケットを送信してマシンを起動する~

投稿日:2020年7月5日 更新日:

Wake On LANを試してみようと以下の記事を書いたわけだが、PowerShellでマジックパケットを送信しようとしたところ、PowerShellのセキュリティや文字コードがややこしいと感じて、自分でプログラム書いたほうがはやいってことになりアプローチした。
会社のPCを電源付けっぱなしはよろしくないんじゃねと思ってWake On LANを試してみた

プログラムに興味ない人は、以下のzip(解凍結果はexe)ダウンロードして使ってみるべし。
SendMagicPacket
コマンドプロンプトで動作するプログラムで.Net Framework 4.6.1が入ってれば動く。Windows 10であれば問題ないでしょ。
コマンド仕様は以下の通り。
●パラメータ1:ポート番号
普通は7か9ということだが、ネットワークによっては閉じられていることもあるかと思って指定できるようにした。9と指定していおけば大丈夫だと思う。
●パラメータ2:ブロードキャストアドレス
ネットワーク内のどの範囲にパケットを送るかの指定で、ディレクテッドブロードキャストアドレスのみが利用できて、255.255.255.255のようなリミテッドブロードキャストアドレスはダメらしい。例えば起動したいIPアドレスが192.168.0.100だとしたら、192.168.0.255としておけばよいはず。
●パラメータ3:MACアドレス
起動したいマシンのMACアドレスで、16進数2桁をハイフンでつなげた文字。例:01-23-45-67-89-0A
●解説
マジックパケットなる一定のルールに基づいたメッセージを、UDPプロトコルでネットワークに送っている。

以下、C#(Visual Studio 2007)のソースコード。コンソールアプリケーションをちゃんと作ったのははじめてかも。パラメータチェック、UDPクライアントのメッセージ送信時の例外処理までやっているのでけっこう使えるものに仕上がったんじゃないか。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace SendMagicPacket
{
	class Program
	{
		static void Main(string[] args)
		{
			if (args.Length != 3)
			{
				Console.Write("パラメータは3つ(1.ポート番号 2.ブロードキャストアドレス 3.MACアドレス");
				return;
			}
			string p1 = args[0];
			int port = -1;
			if (!int.TryParse(p1, out port) && !(0 <= port && port <= 65535))
			{
				Console.Write("パラメータ1(ポート番号)が0~65535でない");
				return;
			}

			string p2 = args[1];
			IPAddress ipaddr;
			if (!IPAddress.TryParse(p2, out ipaddr))
			{
				Console.Write("パラメータ2がIPアドレスではない");
				return;
			}
			string p3 = args[2];
			string[] mac = p3.Split('-');
			if (mac.Length != 6)
			{
				Console.Write("パラメータ3がMACアドレスではない(ハイフンで区切られた6つのセクション)");
				return;
			}
			byte[] macaddr = { 0, 0, 0, 0, 0, 0 };
			for (int i = 0; i < 6; i++)
			{
				byte result = 0;
				try
				{
					result = Convert.ToByte(mac[i], 16);
				}
				catch (FormatException)
				{
					Console.Write("パラメータ3がMACアドレスではない(各セクションに0~9,a~fの文字以外が使われている)");
					return;
				}
				catch (OverflowException)
				{
					Console.Write("パラメータ3がMACアドレスではない(各セクション桁あふれしている)");
					return;
				}
				macaddr[i] = result;
			}
			if (MagicPacket.Send(port, ipaddr, macaddr) == true)
				Console.Write("成功:ポート番号" + p1 + " ブロードキャストアドレス" + p2 + " MACアドレス" + p3);
		}
	}
	static class MagicPacket
	{
		static public bool Send(int port, IPAddress broad, byte[] macAddress)
		{
			try
			{
				MemoryStream stream = new MemoryStream();
				BinaryWriter writer = new BinaryWriter(stream);
				for (int i = 0; i < 6; i++)
					writer.Write((byte)0xff);
				for (int i = 0; i < 16; i++)
					writer.Write(macAddress);
				UdpClient client = new UdpClient();
				client.EnableBroadcast = true;
				client.Send(stream.ToArray(), (int)stream.Position, new IPEndPoint(broad, port));
			}
			catch (ArgumentNullException e)
			{
				Console.Write("ArgumentNullException: {0}", e);
				return false;
			}
			catch (SocketException e)
			{
				Console.Write("SocketException: {0}", e);
				return false;
			}
			return true;
		}
	}
}

ちょっとおまけだけど、上記のclient.Sendをやった後に、client.Close()とやってはいけない。
明示的にCloseしておけばメモリーが解放されていいかと思ったが、このせいでSendが動かなかった。
ということに気付くのに数時間を要してしまった。。

-ソフト開発

執筆者:


comment

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

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

関連記事

PDFアレコレがVectorに掲載されたよん

Vectorのカテゴリとしては文書作成⇒PDF。PDFアレコレというフリーソフトが掲載されたよん。

no image

UNICODE対応プログラム

開発環境:VC6 プリプロセッサの定義に、UNICODE,_UNICODEを追加。(_MBCSをカット) EXEの場合は、エントリポイントシンボルにwWinMainCRTStartupを記述。 ・ch …

no image

通常使うプリンタを取得する

通常使うプリンターを取得する方法をいくつか挙げる。 ①GetDefaultPrinter TCHAR printerName[1024]; DWORD dwBufferSize = 1024; BOO …

no image

レイヤ付きPDFを出力する弊害

Illustratorという高価なアプリを使ってPDFを出力すると、PDFにレイヤが付いてしまって非表示にしたはずのレイヤが表示されて困ったなという事象に2回遭遇したので以下に記録。共通しているのが、 …

Teigha改めODAでDWGをDXFに変換するプログラムをつくってみよう!【Part.3】

Part.2の続編。今回はODAプロジェクトがどんな構造になっているのかを、逐一つまびらかにこんこんと説明してみる。 【1.MFCプロジェクトの作成】 ファイル⇒新規作成⇒プロジェクトで、MFCアプリ …