最近開発で使う端末が増えたのですが、その分各端末を手動で起動・シャットダウンするのが手間になりました。
そのため、WakeOnLANやシャットダウンができるツールを探してみたところ、いろいろとありました。
ただ、C#でネットワーク周りのコードを書いたことがなかったため、どんな書き方をするんだろうと自作してみることにしました。
Wake On LAN部分
Wake On LANで使うマジックパケットの仕様は以下の通りでした。
Wake-on-LAN - Wikipedia
今回はDHCPを使っている端末も含まれていたため、起動させたい端末のMACアドレスを知るために以下の変換を行うことにしました。
ホスト名→IPアドレスの変換は、.NETの以下のメソッドを使えばできました。
System.Net.Dns.GetHostAddresses(hostName)
IPアドレス→ホスト名の変換も.NETにあるのかなと思っていましたが、自分の端末のインタフェースは
System.Net.NetworkInformation.NetworkInterface.GetPhysicalAddress()
で取得できるものの、自分以外の端末のMACアドレスは取得することができないようでした。
他の方法を探してみたものの、
- System.ManagementScopeを使う
- arp.exeを使う
- Win32APIを使う
と少々敷居が高そうだったので、ライブラリを探してみたところ、「SharpPcap」がありました。
SharpPcap プロジェクト日本語トップページ - SourceForge.JP
SharpPcapでは、
など、必要なことができそうだったので、これを使うことにしました。
c# - How to send a WOL package(or anything at all) through a nic which has no IP address? - Stack Overflow
シャットダウン部分
.NETでは機能が見当たりませんでしたので、他の方法を探してみました。
.net - How to shutdown the computer from C# - Stack Overflow
いろいろとあるのですが、結局お手軽な「shutdown」コマンドを使うことにしました。
環境
- WinPcap 4.1.3
公式サイトよりダウンロード・インストールします。
WinPcap · Download
インストールしていない場合、実行時に以下のエラーとなりました。
ハンドルされていない例外: System.DllNotFoundException: DLL 'wpcap' を読み込めません:指定されたモジュールが見つかりません。 (HRESULT からの例外:0x8007007E)
- SharpPcap 4.2.0
NuGetにてインストールすれば、依存しているものも入ります*1。
- Command Line Parser Library 1.9.71
コマンドライン引数の扱いを容易にするため、NuGetにてインストールします。
悩んだことなど
有効なネットワークインタフェースの判定
ネットワークインターフェースは、
SharpPcap.LibPcap.LibPcapLiveDeviceList.Instance
にて取得することができましたが、仮想環境とかを作っていると複数のインタフェースが取得できます。そのため、どれを有効なものと判断するか迷いました。
ただ、手元の環境ではデフォルトゲートウェイが設定されているかどうかで判断できそうだったので、それを採用しました。他の環境では異なると思いますが...
NuGetの利用
今回初めてNuGet(NuGet 2.8)を使いました。
GitHubのVisualStudio向け.gitignoreを入れてGitHubへとcommit・pushした後、cloneしてみました。
ソリューションを開いた当初は、
参照コンポーネント 'CommandLIne' が見つかりませんでした 参照コンポーネント 'PacketDotNet' が見つかりませんでした 参照コンポーネント 'SharpPcap' が見つかりませんでした
という警告がでたものの、そのままビルドしてみたところ、
ファイル packages.configに一覧表示されているNuGetパッケージを復元しています
と表示され、必要なNuGetパッケージはすべて復元され、ビルドも正常に終わりました。
なお、デスクトップアプリだったせいか、NuGet.Configが無くてもパッケージは復元されました。
NuGet 2.7 と Visual Studio におけるパッケージ復元機能の強化 - THE TRUTH IS OUT THERE - Site Home - MSDN Blogs
ソースコード
GitHubに上げておきました。
thinkAmi/WakeOnLAN-Shutdown · GitHub
グループポリシーオブジェクトのローカルコンピューターポリシーにある「スクリプト(スタートアップ/シャットダウン)」などに仕込むことで、自分の端末と連動して起動/シャットダウンができるようになりました。
参考
使ったのがSharpPcap4系だったため、SharpPcap3系とは書き方が少々異なる部分もありますが、参考になります。