MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
C Sharpの基礎 - デバイス情報のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
C Sharpの基礎 - デバイス情報
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == PCのデバイス情報には、以下に示すようなものがある。<br> * CPU *: 種類、速度、コア数 * メモリ *: 容量、種類、速度 * ストレージ *: 種類(HDD / SSD)、容量 * グラフィックカード *: モデル、VRAM容量 * マザーボード *: モデル、チップセット <br> * PCにインストールされているソフトウェア情報 *: OS (種類、バージョン) *: インストールされたドライバ *: インストールされたアプリケーション <br> * ネットワーク情報 *: IPアドレス *: MACアドレス *: ネットワークアダプタの種類 <br> * 周辺機器情報 *: 接続されたモニタ *: プリンタ *: その他のUSBデバイス <br> デバイス情報を取得することのメリットを以下に示す。<br> * アプリケーションのパフォーマンス最適化 *: ハードウェア情報に基づいて処理を調整できる。 * トラブルシューティング *: システム情報を使って問題の原因特定が容易になる。 * ユーザエクスペリエンスの向上 *: デバイスに適したUIや機能を提供できる。 * セキュリティ強化 *: デバイス固有の情報を認証に利用できる。 <br> また、デバイス情報を取得するにあたり、以下に示すようなデメリットも存在する。<br> * プライバシーの懸念 *: ユーザの個人情報を収集する可能性がある。 * セキュリティリスク *: 悪用される可能性のある情報を取得する。 * 互換性の問題 *: OSやハードウェアの変更により、取得方法が変わる可能性がある。 * パフォーマンスへの影響 *: 頻繁な情報取得はシステムに負荷をかける可能性がある。 <br><br> == CPU == ==== LibreHardwareMonitorライブラリ ==== ===== LibreHardwareMonitorライブラリとは ===== LibreHardwareMonitorライブラリは、コンピュータのハードウェア情報を包括的に監視するためのオープンソースライブラリである。<br> 元々は、OpenHardwareMonitorプロジェクトから派生しており、現在も活発に開発が続けられている。<br> <br> LibreHardwareMonitorライブラリの主な特徴は、システムの様々なコンポーネントから詳細な情報を取得できることである。<br> CPU、GPU、マザーボード、RAM、ストレージデバイス、ネットワークアダプタ等、幅広いハードウェアをサポートしている。<br> 各コンポーネントについて、温度、クロック速度、使用率、電圧等の重要なパラメータを監視することができる。<br> <br> LibreHardwareMonitorライブラリの設計は非常に柔軟で、必要な情報のみを選択して取得することができる。<br> 例えば、CPUの情報だけが必要な場合は、他のコンポーネントの監視を無効にすることにより、リソース使用を最適化できる。<br> <br> また、このライブラリは異なるハードウェアメーカーや型番に対応するため、抽象化レイヤーを使用している。<br> これにより、開発者は特定のハードウェアの詳細を気にすることなく、一貫したインターフェースを通じて情報を取得することができる。<br> <br> 性能面では、LibreHardwareMonitorライブラリは一般的に効率的であるが、頻繁に更新を行う場合や全てのセンサを同時に監視する場合には、システムに若干の負荷がかかる可能性がある。<br> そのため、アプリケーションの要件に応じて、更新頻度や監視するコンポーネントを適切に選択することが重要である。<br> <br> LibreHardwareMonitorライブラリは、システムのハードウェア情報を詳細に把握するアプリケーションにとって、強力で信頼性の高いツールである。<br> システム監視、パフォーマンス最適化、ハードウェア診断等、幅広い用途に活用できる有用なライブラリといえる。<br> <br> <u>LibreHardwareMonitorライブラリは、[[その他 - ソフトウェアライセンス#MPL 2.0ライセンス|MPL 2.0ライセンス]]に準拠している。</u><br> <br> * LibreHardwareMonitorライブラリの公式Webサイト *: https://github.com/LibreHardwareMonitor/LibreHardwareMonitor <br> <u>※注意 1</u><br> <u>一部の機能では管理者権限が必要になる場合がある。</u><br> <u>特に、センサからの詳細な読み取りや一部のハードウェア固有の情報を取得する場合が当てはまる。</u><br> <br> <u>※注意 2</u><br> <u>LibreHardwareMonitorライブラリはWindowsプラットフォームで最も広範なサポートを提供している。</u><br> <u>Linux上での使用は可能であるが、一部の機能が制限される、あるいは、追加の設定が必要な場合がある。</u><br> <br> ===== LibreHardwareMonitorライブラリのインストール ===== RiderまたはVisual StudioからNuGetを使用して、LibreHardwareMonitorライブラリをインストールする。<br> * Riderの場合 *# プロジェクトを開く。 *# [ツール]メインメニュー - [Nuget] - [ソリューション の Nuget パッケージを管理] (または、[<プロジェクト名> の Nuget パッケージを管理])を選択する。 *# メイン画面下部にある[パッケージ]タブから <u>LibreHardwareMonitor</u> と入力して検索する。 *# メイン画面下部の右にある[+]ボタンを押下して、LibreHardwareMonitorライブラリをインストールする。 *: <br> * Visual Studioの場合 *# プロジェクトを開く。 *# NuGetパッケージマネージャーを開く。 *#* [ツール]メインメニュー - [NuGetパッケージマネージャー]を選択して、[ソリューションのNuGetパッケージの管理]を選択する。 *#* または、ソリューションエクスプローラーでプロジェクトを右クリックして、コンテキストメニューから[NuGetパッケージの管理]を選択する。 *# LibreHardwareMonitorライブラリを検索する。 *#: NuGetパッケージマネージャーの検索ボックスに <u>LibreHardwareMonitor</u> と入力して検索する。 *# LibreHardwareMonitorライブラリのインストール *#: 検索結果からTomlynLibreHardwareMonitorライブラリを選択して、[インストール]ボタンを押下する。 *# インストールの確認ダイアログが表示されるので、[OK]ボタンを押下してインストールを完了する。 *# 参照の確認 *#: インストールが完了した後、プロジェクトの参照にLibreHardwareMonitorライブラリが追加されていることを確認する。 *: <br> * パッケージマネージャーコンソールからインストールする場合 *# プロジェクトを開く。 *# [表示]メインメニュー - [その他のウィンドウ] - [パッケージマネージャーコンソール]を選択して、パッケージマネージャーコンソールを開く。 *# パッケージマネージャーコンソールから、Tomlynライブラリをダウンロードしてインストールする。 *#: <code>Install-Package LibreHardwareMonitorLib</code> *# ソリューションエクスプローラーのプロジェクトの参照において、LibreHardwareMonitorライブラリが追加されていることを確認する。 *: <br> * <code>dotnet</code>コマンドを使用する場合 *# ターミナルを開く。 *# プロジェクトのルートディレクトリに移動する。 *# LibreHardwareMonitorライブラリをインストールする。 *#: 最新の安定版をインストールする場合 *#: <code>dotnet add package LibreHardwareMonitorLib</code> *#: <br> *#: バージョンを指定してインストールする場合 *#: <code>dotnet add package LibreHardwareMonitorLib --version <バージョン></code> *#: <br> *: <u>※注意</u> *: <u>プロジェクトがGit等のバージョン管理システムを使用している場合、これらの変更がトラッキングされることを確認すること。</u> *: <u>プロジェクトを再ビルドして、新しく追加されたパッケージが正しく統合されていることを確認することを推奨する。</u> <br> プロジェクトにおいて、LibreHardwareMonitorライブラリを使用する場合は、ソースコードファイルの先頭にusingステートメントを追加する。<br> これにより、名前空間を使用することで、LibreHardwareMonitorライブラリに関する主要な機能にアクセスすることができる。<br> <syntaxhighlight lang="c#"> using LibreHardwareMonitor.Hardware; </syntaxhighlight> <br> ===== 使用例 ===== 以下の例では、CPU情報を取得している。<br> また、LibreHardwareMonitorライブラリは、CPU以外の他のデバイス情報も提供しているため、より包括的な情報を取得することができる。<br> <br> <u>※注意 1</u><br> <u>一部の情報 (特に温度や詳細な使用率) を取得する場合は、管理者権限が必要な場合がある。</u><br> <br> <u>※注意 2</u><br> <u>LibreHardwareMonitorライブラリは常に最新のハードウェアに対応しているわけではない。</u><br> <u>特に新しいCPUモデルの場合、一部の情報が正確でない可能性がある。</u><br> <br> <u>※注意 3</u><br> <u>LibreHardwareMonitorライブラリはクロスプラットフォームをサポートしているが、一部の機能はWindowsでのみ動作する可能性がある。</u><br> <br> <syntaxhighlight lang="c#"> using System; using LibreHardwareMonitor.Hardware; class Program { static void Main() { var computer = new Computer { IsCpuEnabled = true, }; computer.Open(); foreach (var hardware in computer.Hardware) { if (hardware.HardwareType == HardwareType.Cpu) { Console.WriteLine($"CPU: {hardware.Name}"); hardware.Update(); foreach (var sensor in hardware.Sensors) { switch (sensor.SensorType) { case SensorType.Clock: Console.WriteLine($"Clock: {sensor.Value} MHz"); break; case SensorType.Temperature: Console.WriteLine($"Temperature: {sensor.Value} °C"); break; case SensorType.Load: Console.WriteLine($"Load: {sensor.Value} %"); break; } } } } computer.Close(); } } </syntaxhighlight> <br> ==== Hardware.Infoライブラリ ==== ===== Hardware.Infoライブラリとは ===== <u>Hardware.Infoライブラリのライセンスは、MITライセンスに準拠している。</u><br> <br> * Hardware.Infoライブラリの公式Webサイト *: https://github.com/Jinjinov/Hardware.Info <br> ===== 取得可能な情報 ===== * BIOS * CPU および SoC * RAM * ストレージドライブ * ネットワークアダプタ * サウンドカード * グラフィックカード * バッテリー * マザーボード * マウス * キーボード * モニタ * プリンタ <br> Hardware.Infoライブラリは、WindowsではWMI、Linuxでは/dev、/proc、/sys、MacOSではsysctl、system_profilerを使用する。<br> <br> ===== Hardware.Infoライブラリのインストール ===== RiderまたはVisual StudioからNuGetを使用して、Hardware.Infoライブラリをインストールする。<br> * Riderの場合 *# プロジェクトを開く。 *# [ツール]メインメニュー - [Nuget] - [ソリューション の Nuget パッケージを管理] (または、[<プロジェクト名> の Nuget パッケージを管理])を選択する。 *# メイン画面下部にある[パッケージ]タブから <u>Hardware.Info</u> と入力して検索する。 *# メイン画面下部の右にある[+]ボタンを押下して、Hardware.Infoライブラリをインストールする。 *: <br> * Visual Studioの場合 *# プロジェクトを開く。 *# NuGetパッケージマネージャーを開く。 *#* [ツール]メインメニュー - [NuGetパッケージマネージャー]を選択して、[ソリューションのNuGetパッケージの管理]を選択する。 *#* または、ソリューションエクスプローラーでプロジェクトを右クリックして、コンテキストメニューから[NuGetパッケージの管理]を選択する。 *# Hardware.Infoライブラリを検索する。 *#: NuGetパッケージマネージャーの検索ボックスに <u>Hardware.Info</u> と入力して検索する。 *# Hardware.Infoライブラリのインストール *#: 検索結果からHardware.Infoライブラリを選択して、[インストール]ボタンを押下する。 *# インストールの確認ダイアログが表示されるので、[OK]ボタンを押下してインストールを完了する。 *# 参照の確認 *#: インストールが完了した後、プロジェクトの参照にHardware.Infoライブラリが追加されていることを確認する。 *: <br> * パッケージマネージャーコンソールからインストールする場合 *# プロジェクトを開く。 *# [表示]メインメニュー - [その他のウィンドウ] - [パッケージマネージャーコンソール]を選択して、パッケージマネージャーコンソールを開く。 *# パッケージマネージャーコンソールから、Hardware.Infoライブラリをダウンロードしてインストールする。 *#: <code>Install-Package Hardware.Info</code> *# ソリューションエクスプローラーのプロジェクトの参照において、Hardware.Infoライブラリが追加されていることを確認する。 *: <br> * <code>dotnet</code>コマンドを使用する場合 *# ターミナルを開く。 *# プロジェクトのルートディレクトリに移動する。 *# Hardware.Infoライブラリをインストールする。 *#: 最新の安定版をインストールする場合 *#: <code>dotnet add package Hardware.Info</code> *#: <br> *#: バージョンを指定してインストールする場合 *#: <code>dotnet add package Hardware.Info --version <バージョン></code> *#: <br> *: <u>※注意</u> *: <u>プロジェクトがGit等のバージョン管理システムを使用している場合、これらの変更がトラッキングされることを確認すること。</u> *: <u>プロジェクトを再ビルドして、新しく追加されたパッケージが正しく統合されていることを確認することを推奨する。</u> <br> プロジェクトにおいて、Hardware.Infoライブラリを使用する場合は、ソースコードファイルの先頭にusingステートメントを追加する。<br> これにより、名前空間を使用することで、Hardware.Infoライブラリに関する主要な機能にアクセスすることができる。<br> <syntaxhighlight lang="c#"> using Hardware.Info; </syntaxhighlight> <br> ===== 使用例 ===== 以下の例では、CPU情報を取得している。<br> <br> HardwareInfoクラスのtimeoutInWMIには、各クエリを実行するManagementObjectSearcherのEnumerationOptionsのTimeoutプロパティを設定する。<br> デフォルト値は、EnumerationOptions.InfiniteTimeoutである。<br> 各ハードウェアコンポーネントには1つ以上のクエリが存在するため、RefreshAllメソッドでは16を超えるクエリが実行される。<br> <br> クエリがタイムアウトに達すると、System.Management.ManagementException例外がスローされる。<br> ここで、ErrorCodeはSystem.Management.ManagementStatus.Timedoutになる。<br> <br> <u>timeoutInWMIを設定する場合は、try-catchブロックを使用する必要がある。</u><br> <br> <syntaxhighlight lang="c#"> using System; using Hardware.Info; class Program { static void Main() { IHardwareInfo hardwareInfo; try { hardwareInfo = new HardwareInfo(timeoutInWMI: TimeSpan.FromMilliseconds(100)); hardwareInfo.RefreshAll(); } catch (ManagementException ex) when (ex.ErrorCode == ManagementStatus.Timedout) { Console.WriteLine(ex); } catch (Exception ex) { Console.WriteLine(ex); } // CPUの情報のみを取得する場合 //IHardwareInfo hardwareInfo = new HardwareInfo(); //hardwareInfo.RefreshCPUList(); foreach (var cpu in hardwareInfo.CpuList) { Console.WriteLine($"CPU Name: {cpu.Name}"); Console.WriteLine($"Manufacturer: {cpu.Manufacturer}"); Console.WriteLine($"Caption: {cpu.Caption}"); Console.WriteLine($"Description: {cpu.Description}"); Console.WriteLine($"Number of Cores: {cpu.NumberOfCores}"); Console.WriteLine($"Number of Logical Processors: {cpu.NumberOfLogicalProcessors}"); Console.WriteLine($"L2 Cache Size: {cpu.L2CacheSize}"); Console.WriteLine($"L3 Cache Size: {cpu.L3CacheSize}"); Console.WriteLine($"Socket Designation: {cpu.SocketDesignation}"); Console.WriteLine($"Max Clock Speed: {cpu.MaxClockSpeed}"); } } } </syntaxhighlight> <br><br> == ネットワークインターフェース == ==== 有線LAN ==== 以下の例では、イーサネット (有線LAN) の情報を取得している。<br> * ネットワークアダプタの説明 * ネットワークアダプタの種類 * MACアドレス * IPv4アドレス (存在する場合) * 全てのIPv6アドレス (存在する場合) <br> IPv6アドレスには、一般的に、グローバルアドレス、リンクローカルアドレス、一時アドレス等、複数の種類が存在する可能性がある。<br> 以下に示すサンプルコードでは、これら全てを表示している。<br> <br> # まず、全てのネットワークインターフェースを取得する。 # イーサネット (有線LAN) インターフェースを検索して、稼働中のインターフェースが存在するかどうかを確認する。 # 存在する場合、そのインターフェースの情報を取得して表示する。 <br> <syntaxhighlight lang="c#"> 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}"); } } } </syntaxhighlight> <br> ==== 無線LAN ==== 以下の例では、無線LANの情報を取得している。<br> * ネットワークアダプタの説明 * ネットワークアダプタの種類 * MACアドレス * IPv4アドレス (存在する場合) * 全てのIPv6アドレス (存在する場合) * SSID * 信号強度 <br> IPv6アドレスには、一般的に、グローバルアドレス、リンクローカルアドレス、一時アドレス等、複数の種類が存在する可能性がある。<br> 以下に示すサンプルコードでは、これら全てを表示している。<br> <br> # まず、全てのネットワークインターフェースを取得する。 # 無線LAN インターフェースを検索して、稼働中のインターフェースが存在するかどうかを確認する。 # 存在する場合、そのインターフェースの情報を取得して表示する。 <br> SSIDと信号強度の取得は、使用するOSやライブラリにより実装方法が異なる。<br> そのため、以下に示すような方法を検討する必要がある。<br> * Windows *: Native Wi-Fi APIを使用する。 *: または、Managed-Wifiライブラリを使用する。 * Linux *: /proc/net/wirelessファイルを読み込む、または、iwconfigコマンドの出力を解析する。 *: <br> *: あるいは、Tmds.DBusライブラリを使用して、NetworkManagerのD-Busを通じてWiFi情報にアクセスする。 *: ただし、NetworkManagerへのアクセスに必要なため、root権限が必要な場合がある。 *: <br> *: プロジェクトにTmds.DBusライブラリを追加する場合は、NuGetパッケージを追加する。<br> *: <code>dotnet add package Tmds.DBus</code> * MacOS *: CoreWLANフレームワークを使用する。 <br> <syntaxhighlight lang="c#"> 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インターフェースメソッド [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(); } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:C_Sharp]]
C Sharpの基礎 - デバイス情報
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse