.NET Core實(shí)現(xiàn)與Windows硬件交互操作的完整指南
.NET Core與Windows硬件交互技術(shù)全景

| 交互方法 | 核心技術(shù) | 典型應(yīng)用場(chǎng)景 | 關(guān)鍵組件/類 | 優(yōu)勢(shì) | 局限性 |
|---|---|---|---|---|---|
| Windows注冊(cè)表操作 | 直接讀寫Windows注冊(cè)表 | 讀取/修改系統(tǒng)配置、應(yīng)用設(shè)置 | Registry, RegistryKey | 直接訪問系統(tǒng)配置,功能全面 | 需處理權(quán)限和異常,不當(dāng)操作有風(fēng)險(xiǎn) |
| WMI查詢 | Windows管理規(guī)范 | 獲取硬件信息(CPU、磁盤、網(wǎng)絡(luò)等) | ManagementObjectSearcher | 信息豐富,標(biāo)準(zhǔn)化接口 | 僅查詢,不能控制,性能開銷較大 |
| .NET IoT庫(kù) | 通過USB轉(zhuǎn)串口適配器 | GPIO、I2C、SPI通信 | Iot.Device.FtCommon, Ft232HDevice | 跨平臺(tái),硬件協(xié)議級(jí)訪問 | 需要特定硬件適配器支持 |
| P/Invoke原生API | 調(diào)用Windows原生API | 觸控板、低級(jí)輸入設(shè)備 | DllImport, 原始輸入API | 直接底層訪問,功能強(qiáng)大 | 復(fù)雜度高,需處理平臺(tái)調(diào)用細(xì)節(jié) |
1. Windows注冊(cè)表操作
原理解說
Windows注冊(cè)表是一個(gè)集中式的層次數(shù)據(jù)庫(kù),存儲(chǔ)了操作系統(tǒng)和應(yīng)用程序的配置信息。通過Microsoft.Win32命名空間,.NET Core應(yīng)用可以訪問和修改這些配置,間接實(shí)現(xiàn)與硬件的交互(如修改顯示設(shè)置、電源管理等)。
核心組件
- Registry類:提供注冊(cè)表根鍵的靜態(tài)訪問,如
Registry.LocalMachine、Registry.CurrentUser等。 - RegistryKey類:代表具體的注冊(cè)表項(xiàng),提供創(chuàng)建、打開、刪除、讀取和寫入等功能。
實(shí)戰(zhàn)示例
using Microsoft.Win32;
using System;
public class RegistryOperations
{
public static void ReadWriteRegistry()
{
try
{
// 在HKEY_CURRENT_USER下創(chuàng)建或打開Software\MyApp子項(xiàng)
using (RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\MyApp"))
{
if (key != null)
{
// 寫入不同類型的值
key.SetValue("Version", "1.0.0", RegistryValueKind.String);
key.SetValue("LastRun", DateTime.Now.ToString(), RegistryValueKind.String);
key.SetValue("StartWithOS", 1, RegistryValueKind.DWord);
// 讀取值
string version = key.GetValue("Version") as string;
string lastRun = key.GetValue("LastRun") as string;
int startWithOS = (int)key.GetValue("StartWithOS", 0);
Console.WriteLine($"版本: {version}, 最后運(yùn)行: {lastRun}, 隨系統(tǒng)啟動(dòng): {startWithOS}");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"注冊(cè)表操作失敗: {ex.Message}");
}
}
// 查詢系統(tǒng)信息示例
public static void ReadSystemInfo()
{
try
{
// 讀取Windows版本信息
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"))
{
if (key != null)
{
string productName = key.GetValue("ProductName") as string;
string currentVersion = key.GetValue("CurrentVersion") as string;
Console.WriteLine($"操作系統(tǒng): {productName}");
Console.WriteLine($"系統(tǒng)版本: {currentVersion}");
}
}
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("權(quán)限不足,無法訪問系統(tǒng)注冊(cè)表");
}
catch (Exception ex)
{
Console.WriteLine($"查詢系統(tǒng)信息失敗: {ex.Message}");
}
}
}
關(guān)鍵注意事項(xiàng)
- 權(quán)限管理:操作
HKEY_LOCAL_MACHINE通常需要管理員權(quán)限。 - 資源釋放:
RegistryKey實(shí)現(xiàn)了IDisposable接口,務(wù)必使用using語(yǔ)句確保資源及時(shí)釋放。 - 數(shù)據(jù)類型:注冊(cè)表支持多種數(shù)據(jù)類型,使用
RegistryValueKind確保數(shù)據(jù)正確存儲(chǔ)。 - 異常處理:注冊(cè)表操作可能拋出
SecurityException、UnauthorizedAccessException等異常,務(wù)必妥善處理。
2. WMI硬件信息查詢
原理解說
WMI(Windows Management Instrumentation)是Windows系統(tǒng)管理的基礎(chǔ)設(shè)施,通過統(tǒng)一的接口提供對(duì)系統(tǒng)硬件和軟件信息的訪問。WMI使用類似SQL的查詢語(yǔ)言(WQL)來查詢系統(tǒng)信息。
核心組件
- ManagementObjectSearcher:執(zhí)行WMI查詢并返回結(jié)果集合。
- ManagementObjectCollection:包含查詢返回的WMI對(duì)象集合。
- ManagementObject:代表單個(gè)WMI對(duì)象,包含屬性和方法。
實(shí)戰(zhàn)示例
using System;
using System.Management;
using System.Collections.Generic;
public class HardwareInfoQuery
{
public static void QueryHardwareInfo()
{
// 示例1:查詢CPU信息
QueryCPUInfo();
// 示例2:查詢磁盤信息
QueryDiskInfo();
// 示例3:查詢網(wǎng)絡(luò)適配器
QueryNetworkAdapters();
}
public static void QueryCPUInfo()
{
try
{
string query = "SELECT * FROM Win32_Processor";
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
{
ManagementObjectCollection results = searcher.Get();
Console.WriteLine("=== CPU信息 ===");
foreach (ManagementObject mo in results)
{
string name = mo["Name"] as string;
string manufacturer = mo["Manufacturer"] as string;
string maxClockSpeed = mo["MaxClockSpeed"] as string;
string cores = mo["NumberOfCores"] as string;
Console.WriteLine($"處理器: {name}");
Console.WriteLine($"制造商: {manufacturer}");
Console.WriteLine($"最大主頻: {maxClockSpeed} MHz");
Console.WriteLine($"核心數(shù): {cores}");
Console.WriteLine("------------------------");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"查詢CPU信息失敗: {ex.Message}");
}
}
public static void QueryDiskInfo()
{
try
{
string query = "SELECT * FROM Win32_LogicalDisk WHERE DriveType = 3";
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
{
ManagementObjectCollection results = searcher.Get();
Console.WriteLine("=== 磁盤信息 ===");
foreach (ManagementObject mo in results)
{
string deviceId = mo["DeviceID"] as string;
string size = mo["Size"] as string;
string freeSpace = mo["FreeSpace"] as string;
if (long.TryParse(size, out long totalSize) &&
long.TryParse(freeSpace, out long free))
{
double totalGB = Math.Round(totalSize / (1024.0 * 1024.0 * 1024.0), 2);
double freeGB = Math.Round(free / (1024.0 * 1024.0 * 1024.0), 2);
double usedPercent = Math.Round((totalSize - free) * 100.0 / totalSize, 2);
Console.WriteLine($"磁盤: {deviceId}");
Console.WriteLine($"總大小: {totalGB} GB");
Console.WriteLine($"可用空間: {freeGB} GB");
Console.WriteLine($"使用率: {usedPercent}%");
Console.WriteLine("------------------------");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"查詢磁盤信息失敗: {ex.Message}");
}
}
public static void QueryNetworkAdapters()
{
try
{
string query = "SELECT * FROM Win32_NetworkAdapter WHERE NetEnabled = True";
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
{
ManagementObjectCollection results = searcher.Get();
Console.WriteLine("=== 網(wǎng)絡(luò)適配器 ===");
foreach (ManagementObject mo in results)
{
string name = mo["Name"] as string;
string adapterType = mo["AdapterType"] as string;
string macAddress = mo["MACAddress"] as string;
string netEnabled = mo["NetEnabled"]?.ToString();
if (!string.IsNullOrEmpty(macAddress))
{
Console.WriteLine($"適配器名稱: {name}");
Console.WriteLine($"類型: {adapterType}");
Console.WriteLine($"MAC地址: {macAddress}");
Console.WriteLine("------------------------");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"查詢網(wǎng)絡(luò)適配器失敗: {ex.Message}");
}
}
}
關(guān)鍵注意事項(xiàng)
- 性能考慮:WMI查詢可能較慢,避免在性能關(guān)鍵路徑中頻繁查詢。
- 異常處理:WMI可能因權(quán)限不足或服務(wù)未運(yùn)行而失敗。
- 字段驗(yàn)證:WMI對(duì)象的屬性可能為null,訪問前應(yīng)進(jìn)行驗(yàn)證。
- 命名空間:需要添加
System.Management包引用。
3. .NET IoT庫(kù)硬件協(xié)議控制
原理解說
.NET IoT庫(kù)為GPIO、I2C、SPI等通用硬件協(xié)議提供了統(tǒng)一的API,可以通過USB轉(zhuǎn)串口適配器(如FTDI FT232H)在普通PC上使用這些協(xié)議與外圍設(shè)備通信。
核心組件
- FtCommon類:提供FTDI設(shè)備檢測(cè)和枚舉功能。
- Ft232HDevice類:代表FT232H適配器設(shè)備,用于創(chuàng)建GPIO、I2C和SPI控制器。
- GpioController類:通用輸入輸出引腳控制。
- I2cDevice類:I2C通信設(shè)備。
實(shí)戰(zhàn)示例
using System;
using System.Device.Gpio;
using System.Device.I2c;
using System.Threading;
using Iot.Device.Ft232H;
using Iot.Device.FtCommon;
using Iot.Device.Bmxx80;
using Iot.Device.Bmxx80.PowerMode;
public class IotHardwareControl
{
public static void ControlGpioAndI2c()
{
// 檢查可用的FTDI設(shè)備
var devices = FtCommon.GetDevices();
if (devices.Count == 0)
{
Console.WriteLine("未找到FTDI設(shè)備,請(qǐng)確保設(shè)備已連接且驅(qū)動(dòng)程序已安裝");
return;
}
Console.WriteLine($"找到 {devices.Count} 個(gè)FTDI設(shè)備");
// 使用第一個(gè)設(shè)備
var device = devices[0];
Console.WriteLine($"使用設(shè)備: {device.Description}");
// GPIO控制示例
GpioControlExample(device);
// I2C設(shè)備示例
I2cDeviceExample(device);
}
public static void GpioControlExample(FtDevice device)
{
try
{
using (var ft232h = new Ft232HDevice(device))
using (var gpio = ft232h.CreateGpioController())
{
// 獲取引腳號(hào)(D7對(duì)應(yīng)FT232H上的物理引腳)
int ledPin = Ft232HDevice.GetPinNumberFromString("D7");
// 打開引腳并設(shè)置為輸出模式
gpio.OpenPin(ledPin, PinMode.Output);
Console.WriteLine("GPIO控制示例: LED閃爍(按任意鍵停止)");
// LED閃爍
bool ledOn = true;
while (!Console.KeyAvailable)
{
gpio.Write(ledPin, ledOn ? PinValue.High : PinValue.Low);
Thread.Sleep(500);
ledOn = !ledOn;
}
Console.ReadKey(); // 清除按鍵
// 關(guān)閉LED并清理資源
gpio.Write(ledPin, PinValue.Low);
gpio.ClosePin(ledPin);
}
}
catch (Exception ex)
{
Console.WriteLine($"GPIO控制失敗: {ex.Message}");
}
}
public static void I2cDeviceExample(FtDevice device)
{
try
{
using (var ft232h = new Ft232HDevice(device))
{
// 創(chuàng)建I2C連接設(shè)置
var i2cSettings = new I2cConnectionSettings(0, 0x76);
// 創(chuàng)建I2C設(shè)備
using (var i2cDevice = ft232h.CreateI2cDevice(i2cSettings))
using (var bme280 = new Bme280(i2cDevice))
{
// 配置傳感器
bme280.SetPowerMode(Bmx280PowerMode.Forced);
int measurementTime = bme280.GetMeasurementDuration();
Console.WriteLine("I2C傳感器讀取示例(BME280):");
// 讀取傳感器數(shù)據(jù)
for (int i = 0; i < 5; i++)
{
bme280.SetPowerMode(Bmx280PowerMode.Forced);
Thread.Sleep(measurementTime);
if (bme280.TryReadTemperature(out var temperature) &&
bme280.TryReadPressure(out var pressure) &&
bme280.TryReadHumidity(out var humidity))
{
Console.WriteLine($"溫度: {temperature.DegreesCelsius:0.##}°C");
Console.WriteLine($"壓力: {pressure.Hectopascals:0.##} hPa");
Console.WriteLine($"濕度: {humidity.Percent:0.##}%");
Console.WriteLine("------------------------");
}
Thread.Sleep(2000);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"I2C設(shè)備操作失敗: {ex.Message}");
}
}
}
關(guān)鍵注意事項(xiàng)
- 驅(qū)動(dòng)程序:確保已安裝FTDI D2XX驅(qū)動(dòng)程序。
- 硬件連接:正確連接硬件引腳,注意I2C和SPI的模式開關(guān)設(shè)置。
- 資源釋放:及時(shí)釋放GPIO引腳和設(shè)備資源。
- 電壓匹配:確保邏輯電平匹配,避免損壞設(shè)備。
4. P/Invoke原生API調(diào)用
原理解說
對(duì)于沒有托管封裝的Windows API,可以通過P/Invoke(Platform Invocation Services)直接調(diào)用原生DLL中的函數(shù)。這種方法適用于需要直接與低級(jí)硬件或系統(tǒng)服務(wù)交互的場(chǎng)景。
實(shí)戰(zhàn)示例:觸控板訪問
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class RawInputTouchpad
{
// 定義Windows API
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern bool RegisterRawInputDevices(
RAWINPUTDEVICE[] pRawInputDevices,
uint uiNumDevices,
uint cbSize);
[DllImport("user32.dll")]
private static extern uint GetRawInputData(
IntPtr hRawInput,
uint uiCommand,
IntPtr pData,
ref uint pcbSize,
uint cbSizeHeader);
// 常量定義
private const int WM_INPUT = 0x00FF;
private const int RIDEV_INPUTSINK = 0x00000100;
private const ushort HID_USAGE_PAGE_GENERIC = 0x01;
private const ushort HID_USAGE_GENERIC_MOUSE = 0x02;
// 結(jié)構(gòu)體定義
[StructLayout(LayoutKind.Sequential)]
public struct RAWINPUTDEVICE
{
public ushort usUsagePage;
public ushort usUsage;
public uint dwFlags;
public IntPtr hwndTarget;
}
private IntPtr _windowHandle;
public RawInputTouchpad(IntPtr windowHandle)
{
_windowHandle = windowHandle;
RegisterForRawInput();
}
private void RegisterForRawInput()
{
RAWINPUTDEVICE[] devices = new RAWINPUTDEVICE[1];
// 注冊(cè)鼠標(biāo)輸入(包括觸控板)
devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
devices[0].usUsage = HID_USAGE_GENERIC_MOUSE;
devices[0].dwFlags = RIDEV_INPUTSINK;
devices[0].hwndTarget = _windowHandle;
if (!RegisterRawInputDevices(devices, (uint)devices.Length,
(uint)Marshal.SizeOf(typeof(RAWINPUTDEVICE))))
{
throw new ApplicationException("注冊(cè)原始輸入設(shè)備失敗");
}
}
// 在窗體中處理WM_INPUT消息
public void ProcessInputMessage(Message m)
{
if (m.Msg == WM_INPUT)
{
uint dataSize = 0;
// 獲取原始輸入數(shù)據(jù)大小
GetRawInputData(m.LParam, 0x10000003, IntPtr.Zero,
ref dataSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER)));
if (dataSize > 0)
{
IntPtr buffer = Marshal.AllocHGlobal((int)dataSize);
try
{
// 獲取實(shí)際數(shù)據(jù)
if (GetRawInputData(m.LParam, 0x10000003, buffer,
ref dataSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))) == dataSize)
{
// 解析觸控板數(shù)據(jù)
ProcessTouchpadData(buffer);
}
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
}
}
private void ProcessTouchpadData(IntPtr rawData)
{
// 這里解析原始輸入數(shù)據(jù)
// 實(shí)際實(shí)現(xiàn)需要根據(jù)觸控板設(shè)備的數(shù)據(jù)格式進(jìn)行解析
Console.WriteLine("收到觸控板輸入數(shù)據(jù)");
}
}
// 在Windows窗體中使用
public partial class MainForm : Form
{
private RawInputTouchpad _touchpad;
public MainForm()
{
InitializeComponent();
_touchpad = new RawInputTouchpad(this.Handle);
}
protected override void WndProc(ref Message m)
{
_touchpad?.ProcessInputMessage(m);
base.WndProc(ref m);
}
}
關(guān)鍵注意事項(xiàng)
- 平臺(tái)依賴性:P/Invoke代碼是Windows特定的,不具備跨平臺(tái)能力。
- 數(shù)據(jù)類型映射:確保正確映射原生類型和托管類型。
- 錯(cuò)誤處理:檢查API返回值,正確處理錯(cuò)誤情況。
- 安全性:原生API調(diào)用可能繞過某些安全限制,需謹(jǐn)慎使用。
以上就是.NET Core實(shí)現(xiàn)與Windows硬件交互操作的完整指南的詳細(xì)內(nèi)容,更多關(guān)于.NET與Windows硬件交互操作的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MVC4制作網(wǎng)站教程第三章 瀏覽用戶組操作3.1
這篇文章主要為大家詳細(xì)介紹了MVC4制作網(wǎng)站教程,瀏覽用戶組功能的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08
asp.net 純真ip庫(kù)取得所在地實(shí)現(xiàn)代碼
asp.net 純真ip庫(kù)取得所在地實(shí)現(xiàn)代碼,需要的朋友可以參考一下。2009-05-05
Asp.net TextBox的TextChanged事件使用介紹
動(dòng)態(tài)創(chuàng)建的控件是如何加載視圖狀態(tài),還提到ProcessPostData方法的調(diào)用,這里我就用TextBox的TextChanged事件來說說視圖數(shù)據(jù)的加載以及事件的觸發(fā)2012-12-12
詳解如何在ASP.NET Core中使用IHttpClientFactory
這篇文章主要介紹了詳解如何在ASP.NET Core中使用IHttpClientFactory,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
asp.net 1.1/ 2.0 中快速實(shí)現(xiàn)單點(diǎn)登陸
asp.net 1.1/ 2.0 中快速實(shí)現(xiàn)單點(diǎn)登陸...2007-04-04
window.showModalDialog兩次加載問題清除緩存方法
window.showModalDialog兩次加載問題:你第一次打開窗口后,第二次瀏覽器沒有從服務(wù)器端取數(shù)據(jù),而直接找到了你已經(jīng)下載的文件2013-08-08
利用Asp.Net回調(diào)機(jī)制實(shí)現(xiàn)進(jìn)度條
本文將利用Asp.Net的回調(diào)機(jī)制使用Js實(shí)現(xiàn)一個(gè)簡(jiǎn)易進(jìn)度條2009-01-01
Asp.net中時(shí)間格式化的6種方法詳細(xì)總結(jié)
數(shù)據(jù)控件綁定時(shí)格式化日期方法/用DataBinder.Eval進(jìn)行數(shù)據(jù)綁定時(shí)/直接用ToString方法轉(zhuǎn)換日期顯示格式/用String類轉(zhuǎn)換日期顯示格式等等,感興趣的你了解下哦,或許對(duì)你學(xué)習(xí)時(shí)間格式化有所幫助2013-02-02

