记录.Net 8 发布增加 PublishTrimmed 裁剪选项,调用WMI 的ManagementObject 异常

最近在做OTA的功能,需要获取到sn做一些业务的逻辑。我们自己实现的库里边的,大部分都是调用 System.Management 的 ManagementObjectSearcher获取 Bios 的序列号

如下所示:

复制代码
 private void BtnWmi_OnClick(object sender, RoutedEventArgs e)
 {
     try
     {
         // 创建 WMI 查询
         ManagementObjectSearcher searcher = new ManagementObjectSearcher(
             "SELECT SerialNumber FROM Win32_BIOS");

         // 遍历查询结果
         foreach (ManagementObject obj in searcher.Get())
         {
             string serialNumber = obj["SerialNumber"]?.ToString();

             if (!string.IsNullOrEmpty(serialNumber))
             {
                 Console.WriteLine($"BIOS 序列号: {serialNumber}");
                 return;
             }
         }

         Console.WriteLine("未找到 BIOS 序列号信息");
     }
     catch (ManagementException ex)
     {
         Console.WriteLine($"WMI 查询错误: {ex.Message}");
     }
     catch (Exception ex)
     {
         Console.WriteLine($"WMI 查询异常错误: {ex.Message}");
     }

 }

由于我们项目现在新建的项目都是基于.Net 8 开发,而且为了兼容多种设备和系统,我们目前的打包方式都是以发布独立部署的方式

同时为了能减少输出文件的大小,我们会启用裁剪的方式 <PublishTrimmed>true</PublishTrimmed>

复制代码
  <PublishTrimmed>true</PublishTrimmed>
  <_SuppressWpfTrimError>true</_SuppressWpfTrimError>
  <BuiltInComInteropSupport>true</BuiltInComInteropSupport>
  <TrimMode>partial</TrimMode>

以上准备工作做好,发布以上的程序,运行发现如下的错误:

查询了官网的资料,有如下的说明:剪裁选项 - .NET | Microsoft Learn

就是启用裁剪会禁用掉某些框架的功能。

解决方法:

参考:使用 C# 远程连接到 WMI - Win32 apps | Microsoft Learn

使用 Microsoft.Management.InfrastructureCimSession 替换WMI 早期的版本

如下所示:

复制代码
 using Microsoft.Management.Infrastructure;

private void BtnCim_OnClick(object sender, RoutedEventArgs e)
 {
     try
     {
         // 创建本地CIM会话
         using (var session = CimSession.Create(null))
         {
             // 查询Win32_BIOS类
             var instances = session.QueryInstances(@"root\cimv2", "WQL", "SELECT SerialNumber FROM Win32_BIOS");
             foreach (var instance in instances)
             {
                 var serialNumber = instance.CimInstanceProperties["SerialNumber"].Value?.ToString();
                 Console.WriteLine($"BIOS 序列号: {serialNumber}");
             }
         }
     }
     catch (Exception ex)
     {
         Console.WriteLine($"错误: {ex.Message}");
     }

 }

不修改发布选项的情况下,运行如下:是可以获取得到Bios的sn的

总结:

1、推荐使用 Microsoft.Management.Infrastructure 的 CimSession 替换 WMI 旧版的 ManagementObject

2、裁剪的选项 PublishTrimmed 如果不介意应用程序的一点体积,是可以忽略不加

参考:

1、剪裁选项 - .NET | Microsoft Learn

2、为应用程序部署创建单个文件 - .NET | Microsoft Learn

3、使用 C# 远程连接到 WMI - Win32 apps | Microsoft Learn

相关推荐
斯内科5 个月前
C#使用WMI获取控制面板中安装的所有程序列表
开发语言·c#·wmi
得鹿梦鱼、2 年前
QT案例 使用WMI获取win_32类的属性值,包括Win32提供程序类中的属性
开发语言·c++·qt·windows api·wmi
pureman_mega2 年前
Windows Management Instrumentation (WMI) 的使用---一些系统接口的替代者
windows·wmi