Khi triển khai chức năng cập nhật qua mạng (OTA), việc truy xuất số sê-ri BIOS là một yêu cầu phổ biến để xác định thiết bị. Trong các dự án dựa trên .NET 8, nhiều nhóm lựa chọn phát hành ứng dụng ở chế độ tự chứa (self-contained) kèm theo tùy chọn cắt giảm mã (trimming) nhằm giảm kích thước đầu ra — đặc biệt quan trọng trên các nền tảng nhúng hoặc thiết bị có giới hạn tài nguyên.
Tuy nhiên, việc kích hoạt <PublishTrimmed>true</PublishTrimmed> cùng với <TrimMode>partial</TrimMode> và hỗ trợ COM nội tại (<BuiltInComInteropSupport>true</BuiltInComInteropSupport>) thường gây ra lỗi khi sử dụng lớp cũ từ System.Management, ví dụ như ManagementObjectSearcher. Nguyên nhân cốt lõi nằm ở việc bộ cắt giảm loại bỏ các thành phần phản xạ và metadata liên quan đến WMI, vốn không được nhận diện là cần thiết trong quá trình phân tích tĩnh.
Dưới đây là đoạn mã minh họa vấn đề:
private void FetchSerialViaWmi()
{
try
{
var query = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BIOS");
foreach (ManagementObject bios in query.Get())
{
var sn = bios["SerialNumber"]?.ToString()?.Trim();
if (!string.IsNullOrWhiteSpace(sn))
{
Console.WriteLine($"[WMI] SN: {sn}");
return;
}
}
Console.WriteLine("[WMI] Không tìm thấy thông tin sê-ri.");
}
catch (Exception ex)
{
Console.WriteLine($"[WMI] Lỗi: {ex.GetType().Name} – {ex.Message}");
}
}Khi chạy phiên bản đã được cắt giảm, đoạn mã trên thường ném ngoại lệ ManagementException với mã lỗi 0x80041002 hoặc NotSupportedException do thiếu các lớp runtime hỗ trợ giao tiếp COM/WMI.
Giải pháp được Microsoft khuyến nghị là chuyển sang thư viện hiện đại hơn: Microsoft.Management.Infrastructure — API CIM chuẩn hóa, được thiết kế để thay thế System.Management trong môi trường .NET Core/.NET 5+ và tương thích đầy đủ với cơ chế cắt giảm.
Ví dụ triển khai thay thế:
using Microsoft.Management.Infrastructure;
private void FetchSerialViaCim()
{
try
{
using var cimSession = CimSession.Create(null); // Kết nối cục bộ
var results = cimSession.QueryInstances(@"root\cimv2", "WQL",
"SELECT SerialNumber FROM Win32_BIOS");
foreach (var obj in results)
{
var prop = obj.CimInstanceProperties.FirstOrDefault(p => p.Name.Equals("SerialNumber", StringComparison.OrdinalIgnoreCase));
if (prop?.Value is string sn && !string.IsNullOrWhiteSpace(sn))
{
Console.WriteLine($"[CIM] SN: {sn}");
return;
}
}
Console.WriteLine("[CIM] Không truy xuất được sê-ri BIOS.");
}
catch (CimException ex)
{
Console.WriteLine($"[CIM] Lỗi CIM: {ex.ErrorCode} – {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"[CIM] Lỗi chung: {ex.Message}");
}
}Lưu ý rằng bạn cần thêm package Microsoft.Management.Infrastructure (phiên bản >= 2.0.0) vào dự án:
<PackageReference Include="Microsoft.Management.Infrastructure" Version="2.0.0" />Đây là giải pháp bền vững cho các ứng dụng .NET 8 trở lên yêu cầu truy vấn WMI/CIM trong môi trường đã được cắt giảm — không cần tắt PublishTrimmed, không cần dùng _SuppressWpfTrimError như một "miếng vá tạm thời", và vẫn đảm bảo khả năng tương thích chéo giữa các phiên bản Windows.