DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

Pingを送信する

.NET Framework 2.0以降で、Pingクラスを使用する

.NET Framework 2.0からは、Pingクラス(System.Net.NetworkInformation名前空間)が追加され、簡単にPingを送信し、結果を受信することができます。

以下に"www.yahoo.com"にPingを送信し、結果を取得する例を示します。

VB.NET
コードを隠すコードを選択
'Pingオブジェクトの作成
Dim p As New System.Net.NetworkInformation.Ping()
'"www.yahoo.com"にPingを送信する
Dim reply As System.Net.NetworkInformation.PingReply = p.Send("www.yahoo.com")

'結果を取得
If reply.Status = System.Net.NetworkInformation.IPStatus.Success Then
    Console.WriteLine("Reply from {0}:bytes={1} time={2}ms TTL={3}", _
        reply.Address, reply.Buffer.Length, _
        reply.RoundtripTime, reply.Options.Ttl)
Else
    Console.WriteLine("Ping送信に失敗。({0})", reply.Status)
End If

p.Dispose()
C#
コードを隠すコードを選択
//Pingオブジェクトの作成
System.Net.NetworkInformation.Ping p =
    new System.Net.NetworkInformation.Ping();
//"www.yahoo.com"にPingを送信する
System.Net.NetworkInformation.PingReply reply = p.Send("www.yahoo.com");

//結果を取得
if (reply.Status == System.Net.NetworkInformation.IPStatus.Success)
{
    Console.WriteLine("Reply from {0}:bytes={1} time={2}ms TTL={3}",
        reply.Address, reply.Buffer.Length,
        reply.RoundtripTime, reply.Options.Ttl);
}
else
{
    Console.WriteLine("Ping送信に失敗。({0})",
        reply.Status);
}

p.Dispose();

上記のようにホスト名(またはIPアドレス)だけを指定してPing.Sendメソッドを呼び出すと、ICMPエコーメッセージと32バイトのデータが送信されます。タイムアウトは、5秒となります。タイムアウトの時間と送信するデータは、Sendメソッドの2番目と3番目のパラメータで指定できます。さらに4番目のパラメータにPingOptionsを指定することにより、パケットの有効期間(TTL:Time to Live)(デフォルトは128)や、ホストに送信するデータを複数のパケットに分割できるか(デフォルトはできる)を指定できます。

非同期的にPingを送信する

非同期的にPingを送信するには、SendAsyncメソッドを呼び出します。結果が分かれば、PingCompletedイベントが発生します。さらに、途中でキャンセルするためにSendAsyncCancelメソッドを使用することもできます。

下に示す例では、Button1をクリックすることにより、Pingを開始します。Button2でキャンセルできます。さらに、タイムアウトやフラグメンテーション、TTLの設定を変更し、送信するデータも指定しています。

VB.NET
コードを隠すコードを選択
'Pingオブジェクト
Dim mainPing As System.Net.NetworkInformation.Ping = Nothing

'Button1のClickイベントハンドラ
Private Sub Button1_Click(ByVal sender As Object, _
        ByVal e As EventArgs) Handles Button1.Click
    Button1.Enabled = False
    Button2.Enabled = True

    'Pingオブジェクトの作成
    If mainPing Is Nothing Then
        mainPing = New System.Net.NetworkInformation.Ping()
        'イベントハンドラを追加
        AddHandler mainPing.PingCompleted, AddressOf Ping_PingCompleted
    End If
    'Pingのオプションを設定
    'TTLを64、フラグメンテーションを無効にする
    Dim opts As New System.Net.NetworkInformation.PingOptions(64, True)
    'Pingで送信する32バイトのデータを作成
    Dim bs As Byte() = System.Text.Encoding.ASCII.GetBytes(New String("A"c, 32))

    '"www.yahoo.com"にPingを送信する
    'タイムアウトを10秒
    mainPing.SendAsync("www.yahoo.com", 10000, bs, opts, Nothing)
End Sub

'Button2のClickイベントハンドラ
Private Sub Button2_Click(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles Button2.Click
    'Pingをキャンセル
    If Not (mainPing Is Nothing) Then
        mainPing.SendAsyncCancel()
    End If
End Sub

Private Sub Ping_PingCompleted(ByVal sender As Object, _
        ByVal e As System.Net.NetworkInformation.PingCompletedEventArgs)
    If e.Cancelled Then
        Console.WriteLine("Pingがキャンセルされました。")
    Else If Not (e.Error Is Nothing) Then
        Console.WriteLine(("エラー:" + e.Error.Message))
    Else
        '結果を取得
        If e.Reply.Status = System.Net.NetworkInformation.IPStatus.Success Then
            Console.WriteLine("Reply from {0}:bytes={1} time={2}ms TTL={3}", _
                e.Reply.Address, e.Reply.Buffer.Length, _
                e.Reply.RoundtripTime, e.Reply.Options.Ttl)
        Else
            Console.WriteLine("Ping送信に失敗。({0})", e.Reply.Status)
        End If
    End If

    Button1.Enabled = True
    Button2.Enabled = False
End Sub
C#
コードを隠すコードを選択
//Pingオブジェクト
System.Net.NetworkInformation.Ping mainPing = null;

//Button1のClickイベントハンドラ
private void Button1_Click(object sender, EventArgs e)
{
    Button1.Enabled = false;
    Button2.Enabled = true;

    //Pingオブジェクトの作成
    if (mainPing == null)
    {
        mainPing = new System.Net.NetworkInformation.Ping();
        //イベントハンドラを追加
        mainPing.PingCompleted +=
            new System.Net.NetworkInformation.PingCompletedEventHandler(
                Ping_PingCompleted);
    }
    //Pingのオプションを設定
    //TTLを64、フラグメンテーションを無効にする
    System.Net.NetworkInformation.PingOptions opts =
        new System.Net.NetworkInformation.PingOptions(64, true);
    //Pingで送信する32バイトのデータを作成
    byte[] bs = System.Text.Encoding.ASCII.GetBytes(new string('A', 32));
    //"www.yahoo.com"にPingを送信する
    //タイムアウトを10秒
    mainPing.SendAsync("www.yahoo.com", 10000, bs, opts, null);
}

//Button2のClickイベントハンドラ
private void Button2_Click(object sender, EventArgs e)
{
    //Pingをキャンセル
    if (mainPing != null)
    {
        mainPing.SendAsyncCancel();
    }
}

private void Ping_PingCompleted(object sender,
    System.Net.NetworkInformation.PingCompletedEventArgs e)
{
    if (e.Cancelled)
    {
        Console.WriteLine("Pingがキャンセルされました。");
    }
    else if (e.Error != null)
    {
        Console.WriteLine("エラー:" + e.Error.Message);
    }
    else
    {
        //結果を取得
        if (e.Reply.Status == System.Net.NetworkInformation.IPStatus.Success)
        {
            Console.WriteLine("Reply from {0}:bytes={1} time={2}ms TTL={3}",
                e.Reply.Address, e.Reply.Buffer.Length,
                e.Reply.RoundtripTime, e.Reply.Options.Ttl);
        }
        else
        {
            Console.WriteLine("Ping送信に失敗。({0})", e.Reply.Status);
        }
    }

    Button1.Enabled = true;
    Button2.Enabled = false;
}

.NET Framework 2.0以降のVB.NETで、My.Computer.Network.Pingメソッドを使用する方法

.NET Framework 2.0以降のVB.NETでは、My.Computer.Network.Pingメソッドを使うこともできます。

VB.NET
コードを隠すコードを選択
If My.Computer.Network.Ping("www.yahoo.com") Then
    Console.WriteLine("Pingに成功。")
Else
    Console.WriteLine("Pingに失敗。")
End If

WMIを使用する

WMIのWin32_PingStatusクラスを使用することもできます。ただし、Win32_PingStatusクラスはWindows XP以上でしか使用できません。

下の例ではSystem.Management.dllを参照設定に追加する必要があります。

VB.NET
コードを隠すコードを選択
'Ping送信先のアドレス
Dim address As String = "www.yahoo.com"

Dim mo As New System.Management.ManagementObject( _
    String.Format("Win32_PingStatus.address='{0}'", address))
If Convert.ToInt64(mo.Properties("StatusCode").Value) = 0 Then
    Console.WriteLine("成功しました。")
Else
    Console.WriteLine("失敗しました。")
End If
mo.Dispose()
C#
コードを隠すコードを選択
//Ping送信先のアドレス
string address = "www.yahoo.com";

System.Management.ManagementObject mo =
    new System.Management.ManagementObject(
        string.Format("Win32_PingStatus.address='{0}'", address));
if (((uint)mo.Properties["StatusCode"].Value) == 0)
{
    Console.WriteLine("成功しました。");
}
else
{
    Console.WriteLine("失敗しました。");
}
mo.Dispose();

ちなみにManagementObjectSearcherクラスを使って同じことを行うと、以下のようになります。

VB.NET
コードを隠すコードを選択
'Ping送信先のアドレス
Dim address As String = "www.yahoo.com"

Dim search As New System.Management.ManagementObjectSearcher( _
    String.Format("select * from Win32_PingStatus where address='{0}'", _
        address))
Dim moc As System.Management.ManagementObjectCollection = search.Get()
Dim mo As System.Management.ManagementObject
For Each mo In moc
    If Convert.ToInt64(mo.Properties("StatusCode").Value) = 0 Then
        Console.WriteLine("成功しました。")
    Else
        Console.WriteLine("失敗しました。")
    End If
    mo.Dispose()
Next mo

moc.Dispose()
search.Dispose()
C#
コードを隠すコードを選択
//Ping送信先のアドレス
string address = "www.yahoo.com";

System.Management.ManagementObjectSearcher search =
    new System.Management.ManagementObjectSearcher(
    string.Format("select * from Win32_PingStatus where address='{0}'",
        address));
System.Management.ManagementObjectCollection moc = search.Get();
foreach (System.Management.ManagementObject mo in moc)
{
    if (((uint)mo.Properties["StatusCode"].Value) == 0)
    {
        Console.WriteLine("成功しました。");
    }
    else
    {
        Console.WriteLine("失敗しました。");
    }
    mo.Dispose();
}

moc.Dispose();
search.Dispose();

Ping.exeを使用する

DOSコマンドツールであるPing.exeを使う方法も考えられます。Ping.exeは、Pingに成功すると、終了コードに0を返します。

VB.NET
コードを隠すコードを選択
Dim address As String = "www.yahoo.com"

Dim psi As New System.Diagnostics.ProcessStartInfo()
'ComSpecのパスを取得する
psi.FileName = "ping"
'コマンドラインを指定
psi.Arguments = address
'ウィンドウを表示しないようにする
psi.UseShellExecute = False
psi.CreateNoWindow = True
'起動
Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start(psi)
p.WaitForExit()
'結果を表示
If p.ExitCode = 0 Then
    Console.WriteLine("Pingに成功しました。")
Else
    Console.WriteLine("Pingに失敗しました。")
End If
C#
コードを隠すコードを選択
string address = "www.yahoo.com";

System.Diagnostics.ProcessStartInfo psi =
    new System.Diagnostics.ProcessStartInfo();
//ComSpecのパスを取得する
psi.FileName = "ping";
//コマンドラインを指定
psi.Arguments = address;
//ウィンドウを表示しないようにする
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
//起動
System.Diagnostics.Process p = System.Diagnostics.Process.Start(psi);
p.WaitForExit();
//結果を表示
if (p.ExitCode == 0)
{
    Console.WriteLine("Pingに成功しました。");
}
else
{
    Console.WriteLine("Pingに失敗しました。");
}

"ping /?"により表示させたping.exeの使い方は、以下のとおりです(Windows XP)。

Usage: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS]
            [-r count] [-s count] [[-j host-list] | [-k host-list]]
            [-w timeout] target_name

Options:
    -t             Ping the specified host until stopped.
                   To see statistics and continue - type Control-Break;
                   To stop - type Control-C.
    -a             Resolve addresses to hostnames.
    -n count       Number of echo requests to send.
    -l size        Send buffer size.
    -f             Set Don't Fragment flag in packet.
    -i TTL         Time To Live.
    -v TOS         Type Of Service.
    -r count       Record route for count hops.
    -s count       Timestamp for count hops.
    -j host-list   Loose source route along host-list.
    -k host-list   Strict source route along host-list.
    -w timeout     Timeout in milliseconds to wait for each reply.

Socketクラスを使用する

Pingクラスを使用できない.NET Framework 1.1以前では、Socketクラスを使用して同様のことを行いことができます。ただしそれなりの知識が必要で、複雑になりますので、具体的な方法については、以下のページを参考にしてください。

  • 履歴:
  • 2010/5/16 「WMIを使用する」のVB.NETのコードが.NET Framework 1.1で動かなかった問題を修正。「Socketクラスを使用する」のリンク先を変更。
  • 2015/3/16 Ping.exeを使用するサンプルで、UseShellExecuteをFalseに設定するようにした。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • 「???を参照に追加します」の意味が分からないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。