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

| 交互方法 | 核心技術(shù) | 典型應(yīng)用場景 | 關(guān)鍵組件/類 | 優(yōu)勢 | 局限性 |
|---|---|---|---|---|---|
| Windows注冊表操作 | 直接讀寫Windows注冊表 | 讀取/修改系統(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庫 | 通過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注冊表操作
原理解說
Windows注冊表是一個(gè)集中式的層次數(shù)據(jù)庫,存儲(chǔ)了操作系統(tǒng)和應(yīng)用程序的配置信息。通過Microsoft.Win32命名空間,.NET Core應(yīng)用可以訪問和修改這些配置,間接實(shí)現(xiàn)與硬件的交互(如修改顯示設(shè)置、電源管理等)。
核心組件
- Registry類:提供注冊表根鍵的靜態(tài)訪問,如
Registry.LocalMachine、Registry.CurrentUser等。 - RegistryKey類:代表具體的注冊表項(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($"注冊表操作失敗: {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)注冊表");
}
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語句確保資源及時(shí)釋放。 - 數(shù)據(jù)類型:注冊表支持多種數(shù)據(jù)類型,使用
RegistryValueKind確保數(shù)據(jù)正確存儲(chǔ)。 - 異常處理:注冊表操作可能拋出
SecurityException、UnauthorizedAccessException等異常,務(wù)必妥善處理。
2. WMI硬件信息查詢
原理解說
WMI(Windows Management Instrumentation)是Windows系統(tǒng)管理的基礎(chǔ)設(shè)施,通過統(tǒng)一的接口提供對(duì)系統(tǒng)硬件和軟件信息的訪問。WMI使用類似SQL的查詢語言(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庫硬件協(xié)議控制
原理解說
.NET IoT庫為GPIO、I2C、SPI等通用硬件協(xié)議提供了統(tǒng)一的API,可以通過USB轉(zhuǎn)串口適配器(如FTDI FT232H)在普通PC上使用這些協(xié)議與外圍設(shè)備通信。
核心組件
- FtCommon類:提供FTDI設(shè)備檢測和枚舉功能。
- 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è)備,請確保設(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ù)交互的場景。
實(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];
// 注冊鼠標(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("注冊原始輸入設(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硬件交互操作的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
ASP.NET連接 Access數(shù)據(jù)庫的幾種方法
這篇文章主要介紹了ASP.NET連接 Access數(shù)據(jù)庫的幾種方法,每種方法都非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友一起學(xué)習(xí)吧2016-08-08
詳解ASP.NET?Core高性能服務(wù)器HTTP.SYS
HTTP.SYS本質(zhì)上就是一個(gè)HTTP/HTTPS監(jiān)聽器,它是Windows網(wǎng)絡(luò)子系統(tǒng)的一部分,是一個(gè)在內(nèi)核模式下運(yùn)行的網(wǎng)絡(luò)驅(qū)動(dòng),今天通過本文給大家介紹下ASP.NET?Core高性能服務(wù)器HTTP.SYS,感興趣的朋友一起看看吧2022-04-04
ASP.NET中如何實(shí)現(xiàn)回調(diào)
這篇文章主要為大家詳細(xì)介紹了ASP.NET中如何實(shí)現(xiàn)回調(diào)操作,感興趣的小伙伴們可以參考一下2016-04-04
asp.net音頻轉(zhuǎn)換之.amr轉(zhuǎn).mp3(利用ffmpeg轉(zhuǎn)換法)
AMR轉(zhuǎn)MP3可實(shí)現(xiàn)將手機(jī)上的AMR錄音轉(zhuǎn)換成流行的MP3格式,以適用更廣泛的應(yīng)用。AMR的體積非常小,適用于存儲(chǔ)在手機(jī)中,當(dāng)我們想將在手機(jī)上的音頻上傳到網(wǎng)絡(luò),就需要將其轉(zhuǎn)換成MP3等流行的格式,本文就是介紹asp.net利用ffmpeg轉(zhuǎn)換法將.amr轉(zhuǎn).mp3的方法,下面來一起看看吧。2016-12-12
LazyCaptcha自定義隨機(jī)驗(yàn)證碼和字體的示例詳解
LazyCaptcha是仿EasyCaptcha和SimpleCaptcha,基于.Net?Standard?2.1的圖形驗(yàn)證碼模塊,這篇文章主要介紹了LazyCaptcha自定義隨機(jī)驗(yàn)證碼和字體?,需要的朋友可以參考下2022-03-03
ASP.NET2.0中用Gridview控件操作數(shù)據(jù)的代碼
在ASP.NET 2.0中,加入了許多新的功能和控件,相比asp.net 1.0/1.1,在各方面都有了很大的提高2012-10-10
ASP.NET Core利用Jaeger實(shí)現(xiàn)分布式追蹤詳解
這篇文章主要給大家介紹了關(guān)于ASP.NET Core利用Jaeger實(shí)現(xiàn)分布式追蹤的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用ASP.NET Core具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04

