C Sharpの基礎 - デバイス情報

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

PCのデバイス情報には、以下に示すようなものがある。

  • CPU
    種類、速度、コア数
  • メモリ
    容量、種類、速度
  • ストレージ
    種類(HDD / SSD)、容量
  • グラフィックカード
    モデル、VRAM容量
  • マザーボード
    モデル、チップセット


  • PCにインストールされているソフトウェア情報
    OS (種類、バージョン)
    インストールされたドライバ
    インストールされたアプリケーション


  • ネットワーク情報
    IPアドレス
    MACアドレス
    ネットワークアダプタの種類


  • 周辺機器情報
    接続されたモニタ
    プリンタ
    その他のUSBデバイス


デバイス情報を取得することのメリットを以下に示す。

  • アプリケーションのパフォーマンス最適化
    ハードウェア情報に基づいて処理を調整できる。
  • トラブルシューティング
    システム情報を使って問題の原因特定が容易になる。
  • ユーザエクスペリエンスの向上
    デバイスに適したUIや機能を提供できる。
  • セキュリティ強化
    デバイス固有の情報を認証に利用できる。


また、デバイス情報を取得するにあたり、以下に示すようなデメリットも存在する。

  • プライバシーの懸念
    ユーザの個人情報を収集する可能性がある。
  • セキュリティリスク
    悪用される可能性のある情報を取得する。
  • 互換性の問題
    OSやハードウェアの変更により、取得方法が変わる可能性がある。
  • パフォーマンスへの影響
    頻繁な情報取得はシステムに負荷をかける可能性がある。



ネットワークインターフェース

有線LAN

以下の例では、イーサネット (有線LAN) の情報を取得している。

  • ネットワークアダプタの説明
  • ネットワークアダプタの種類
  • MACアドレス
  • IPv4アドレス (存在する場合)
  • 全てのIPv6アドレス (存在する場合)


IPv6アドレスには、一般的に、グローバルアドレス、リンクローカルアドレス、一時アドレス等、複数の種類が存在する可能性がある。
以下に示すサンプルコードでは、これら全てを表示している。

  1. まず、全てのネットワークインターフェースを取得する。
  2. イーサネット (有線LAN) インターフェースを検索して、稼働中のインターフェースが存在するかどうかを確認する。
  3. 存在する場合、そのインターフェースの情報を取得して表示する。


 using System;
 using System.Linq;
 using System.Net.NetworkInformation;
 using System.Net.Sockets;
 
 namespace GetWiredMACAddress;
 
 class Program
 {
    public static void Main()
    {
       try {
          foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) {
             // 稼働中のイーサネット (有線LAN) インターフェースの情報を検索
             if (nic.NetworkInterfaceType == NetworkInterfaceType.Ethernet &&
                 nic.OperationalStatus == OperationalStatus.Up) {
 
                Console.WriteLine($"ネットワークアダプタ: {nic.Description}");
                Console.WriteLine($"アダプタの種類: {nic.NetworkInterfaceType}");
 
                // 稼働中の有線LANのMACアドレスを取得して文字列形式に変換
                // 表示形式は、16進数の大文字 (AA-BB-CC-DD-EE-FF)
                PhysicalAddress mac = nic.GetPhysicalAddress();
                string macAddress   = BitConverter.ToString(mac.GetAddressBytes()).Replace("-", ":");
                Console.WriteLine($"MACアドレス: {macAddress}");
 
                // 稼働中の有線LANのIPアドレスを取得
                var ipProperties = nic.GetIPProperties();
 
                // 稼働中の有線LANのIPv4アドレスを取得
                var ipv4Address = ipProperties.UnicastAddresses
                                              .FirstOrDefault(addr => addr.Address.AddressFamily == AddressFamily.InterNetwork);
 
                if (ipv4Address != null) {
                   Console.WriteLine($"IPv4アドレス: {ipv4Address.Address}");
                }
                else {
                   Console.WriteLine("IPv4アドレスが見つかりません。");
                }
 
                // 稼働中の有線LANのIPv6アドレスを取得
                var ipv6Addresses = ipProperties.UnicastAddresses
                                                .Where(addr => addr.Address.AddressFamily == AddressFamily.InterNetworkV6)
                                                .Select(addr => addr.Address)
                                                .ToList();
 
                if (ipv6Addresses.Any()) {
                   Console.WriteLine("IPv6アドレス:");
                   foreach (var ipv6 in ipv6Addresses) {
                      Console.WriteLine($"{ipv6}");
                   }
                }
                else {
                   Console.WriteLine("IPv6アドレスが見つかりません。");
                }
             }
          }
       }
       catch (Exception ex) {
          Console.WriteLine($"エラーが発生しました: {ex.Message}");
       }
    }
 }


無線LAN

以下の例では、無線LANの情報を取得している。

  • ネットワークアダプタの説明
  • ネットワークアダプタの種類
  • MACアドレス
  • IPv4アドレス (存在する場合)
  • 全てのIPv6アドレス (存在する場合)
  • SSID
  • 信号強度


IPv6アドレスには、一般的に、グローバルアドレス、リンクローカルアドレス、一時アドレス等、複数の種類が存在する可能性がある。
以下に示すサンプルコードでは、これら全てを表示している。

  1. まず、全てのネットワークインターフェースを取得する。
  2. 無線LAN インターフェースを検索して、稼働中のインターフェースが存在するかどうかを確認する。
  3. 存在する場合、そのインターフェースの情報を取得して表示する。


SSIDと信号強度の取得は、使用するOSやライブラリにより実装方法が異なる。
そのため、以下に示すような方法を検討する必要がある。

  • Windows
    Native Wi-Fi APIを使用する。
    または、Managed-Wifiライブラリを使用する。
  • Linux
    /proc/net/wirelessファイルを読み込む、または、iwconfigコマンドの出力を解析する。

    あるいは、Tmds.DBusライブラリを使用して、NetworkManagerのD-Busを通じてWiFi情報にアクセスする。
    ただし、NetworkManagerへのアクセスに必要なため、root権限が必要な場合がある。

    プロジェクトにTmds.DBusライブラリを追加する場合は、NuGetパッケージを追加する。
    dotnet add package Tmds.DBus
  • MacOS
    CoreWLANフレームワークを使用する。


 using System;
 using System.Linq;
 using System.Net.NetworkInformation;
 using System.Net.Sockets;
 using System.Threading.Tasks;
 using Tmds.DBus;
 
 namespace GetWiredMACAddress;
 
 class Program
 {
    public static void Main()
    {
       try {
          foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) {
             // 稼働中のイーサネット (無線LAN) インターフェースの情報を検索
             if (nic.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 &&
                 nic.OperationalStatus == OperationalStatus.Up) {
 
                Console.WriteLine($"ネットワークアダプタ: {nic.Description}");
                Console.WriteLine($"アダプタの種類: {nic.NetworkInterfaceType}");
 
                // 稼働中の無線LANのMACアドレスを取得して文字列形式に変換
                // 表示形式は、16進数の大文字 (AA-BB-CC-DD-EE-FF)
                PhysicalAddress mac = nic.GetPhysicalAddress();
                string macAddress   = BitConverter.ToString(mac.GetAddressBytes()).Replace("-", ":");
                Console.WriteLine($"MACアドレス: {macAddress}");
 
                // 稼働中の無線LANのIPアドレスを取得
                var ipProperties = nic.GetIPProperties();
 
                // 稼働中の有線LANのIPv4アドレスを取得
                var ipv4Address = ipProperties.UnicastAddresses
                                              .FirstOrDefault(addr => addr.Address.AddressFamily == AddressFamily.InterNetwork);
 
                if (ipv4Address != null) {
                   Console.WriteLine($"IPv4アドレス: {ipv4Address.Address}");
                }
                else {
                   Console.WriteLine("IPv4アドレスが見つかりません。");
                }
 
                // 稼働中の無線LANのIPv6アドレスを取得
                var ipv6Addresses = ipProperties.UnicastAddresses
                                                .Where(addr => addr.Address.AddressFamily == AddressFamily.InterNetworkV6)
                                                .Select(addr => addr.Address)
                                                .ToList();
 
                if (ipv6Addresses.Any()) {
                   Console.WriteLine("IPv6アドレス:");
                   foreach (var ipv6 in ipv6Addresses) {
                      Console.WriteLine($"{ipv6}");
                   }
                }
                else {
                   Console.WriteLine("IPv6アドレスが見つかりません。");
                }
 
                // SSIDおよび信号強度の取得
                var (ssid, strength) = await GetWifiInfo(nic.Name);
                Console.WriteLine($"SSID: {ssid}");
                Console.WriteLine($"信号強度: {strength}");
             }
          }
       }
       catch (Exception ex) {
          Console.WriteLine($"エラーが発生しました: {ex.Message}");
       }
    }
 
    // D-Busを使用してSSIDおよび信号強度を取得する
    static async Task<(string ssid, int strength)> GetWifiInfo(string interfaceName)
    {
       var connection = Connection.System;
       var nmManager = connection.CreateProxy<INetworkManager>("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager");
 
       var devices = await nmManager.GetDevicesAsync();
       foreach (var devicePath in devices) {
          var device          = connection.CreateProxy<IDevice>("org.freedesktop.NetworkManager", devicePath);
          var deviceInterface = await device.GetInterfaceAsync();
             
          if (deviceInterface == interfaceName) {
             var wifiDevice        = connection.CreateProxy<IWifiDevice>("org.freedesktop.NetworkManager", devicePath);
             var activeAccessPoint = await wifiDevice.GetActiveAccessPointAsync();
                 
             if (activeAccessPoint != "/") {
                var ap       = connection.CreateProxy<IAccessPoint>("org.freedesktop.NetworkManager", activeAccessPoint);
                var ssid     = System.Text.Encoding.UTF8.GetString(await ap.GetSsidAsync());
                var strength = await ap.GetStrengthAsync();
 
                return (ssid, strength);
             }
          }
       }
 
       return ("Not connected", 0);
    }
 }
 
 // Linux
 // NetworkManagerのD-Busインターフェース名およびD-Busインターフェースメソッド (Linux)
 [DBusInterface("org.freedesktop.NetworkManager")]
 interface INetworkManager
 {
    Task<ObjectPath[]> GetDevicesAsync();
 }
 
 [DBusInterface("org.freedesktop.NetworkManager.Device")]
 interface IDevice
 {
    Task<string> GetInterfaceAsync();
 }
 
 [DBusInterface("org.freedesktop.NetworkManager.Device.Wireless")]
 interface IWifiDevice
 {
    Task<ObjectPath> GetActiveAccessPointAsync();
 }
 
 [DBusInterface("org.freedesktop.NetworkManager.AccessPoint")]
 interface IAccessPoint
 {
    Task<byte[]> GetSsidAsync();
    Task<byte> GetStrengthAsync();
 }