You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET中GetFirmwareEnvironmentVariable函数调用异常排查

解决GetFirmwareEnvironmentVariable读取乱码及空数组问题

核心问题分析

你遇到的乱码、空数组问题本质是两个原因:

  1. P/Invoke定义不规范:错误的字符集、缓冲区处理方式导致字符串类变量解析异常;
  2. UEFI变量数据类型误解:并非所有变量都是字符串类型,像SecureBoot是单字节布尔值、TimeOut是4字节无符号整数,直接按字符串读取必然出现乱码或空数组。

修正后的P/Invoke实现及辅助方法

以下是适配UEFI变量类型的VB.NET代码,包含不同类型变量的读取逻辑:

Imports System.Runtime.InteropServices

Public Class UefiVariableHelper
    ' 全局UEFI变量通用GUID:{8BE4DF61-93CA-11D2-AA0D-00E098032B8C}
    Public Shared ReadOnly EFI_GLOBAL_VARIABLE_GUID As New Guid("8BE4DF61-93CA-11D2-AA0D-00E098032B8C")

    ' 标准P/Invoke定义:使用Unicode字符集,正确处理缓冲区大小
    <DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
    Public Shared Function GetFirmwareEnvironmentVariable(
        ByVal lpName As String,
        ByVal lpGuid As String,
        ByVal lpBuffer As IntPtr,
        ByRef nSize As UInteger
    ) As UInteger
    End Function

    ' 读取UTF-16LE字符串类型的UEFI变量(如PlatformLang、PlatformLangCodes)
    Public Shared Function ReadStringVariable(variableName As String, targetGuid As Guid) As String
        Dim guidStr As String = targetGuid.ToString("B").ToUpper()
        Dim requiredSize As UInteger = 0

        ' 先获取变量所需的缓冲区大小
        GetFirmwareEnvironmentVariable(variableName, guidStr, IntPtr.Zero, requiredSize)
        If requiredSize = 0 Then Return Nothing

        Dim buffer As IntPtr = Marshal.AllocHGlobal(CInt(requiredSize))
        Try
            Dim readBytes As UInteger = GetFirmwareEnvironmentVariable(variableName, guidStr, buffer, requiredSize)
            If readBytes = 0 Then Return Nothing

            ' UEFI字符串以UTF-16LE编码,直接转换为.NET字符串
            Return Marshal.PtrToStringUni(buffer, CInt((requiredSize - 2) / 2)) ' 去除末尾的空终止符
        Finally
            Marshal.FreeHGlobal(buffer)
        End Try
    End Function

    ' 读取布尔类型的UEFI变量(如SecureBoot,1字节UINT8)
    Public Shared Function ReadBooleanVariable(variableName As String, targetGuid As Guid) As Boolean?
        Dim guidStr As String = targetGuid.ToString("B").ToUpper()
        Const bufferSize As UInteger = 1 ' UINT8占用1字节

        Dim buffer As IntPtr = Marshal.AllocHGlobal(CInt(bufferSize))
        Try
            Dim readBytes As UInteger = GetFirmwareEnvironmentVariable(variableName, guidStr, buffer, bufferSize)
            If readBytes = 0 Then Return Nothing

            Return Marshal.ReadByte(buffer) <> 0
        Finally
            Marshal.FreeHGlobal(buffer)
        End Try
    End Function

    ' 读取无符号32位整数类型的UEFI变量(如TimeOut,4字节UINT32)
    Public Shared Function ReadUInt32Variable(variableName As String, targetGuid As Guid) As UInteger?
        Dim guidStr As String = targetGuid.ToString("B").ToUpper()
        Const bufferSize As UInteger = 4 ' UINT32占用4字节

        Dim buffer As IntPtr = Marshal.AllocHGlobal(CInt(bufferSize))
        Try
            Dim readBytes As UInteger = GetFirmwareEnvironmentVariable(variableName, guidStr, buffer, bufferSize)
            If readBytes = 0 Then Return Nothing

            Return Marshal.ReadUInt32(buffer)
        Finally
            Marshal.FreeHGlobal(buffer)
        End Try
    End Function
End Class

使用示例

' 读取字符串类型变量
Dim platformLang = UefiVariableHelper.ReadStringVariable("PlatformLang", UefiVariableHelper.EFI_GLOBAL_VARIABLE_GUID)
Console.WriteLine($"PlatformLang: {platformLang}")

' 读取SecureBoot状态
Dim secureBootStatus = UefiVariableHelper.ReadBooleanVariable("SecureBoot", UefiVariableHelper.EFI_GLOBAL_VARIABLE_GUID)
Console.WriteLine($"SecureBoot: {If(secureBootStatus.HasValue, secureBootStatus.Value, "读取失败")}")

' 读取启动超时时间
Dim bootTimeout = UefiVariableHelper.ReadUInt32Variable("TimeOut", UefiVariableHelper.EFI_GLOBAL_VARIABLE_GUID)
Console.WriteLine($"启动超时: {If(bootTimeout.HasValue, $"{bootTimeout.Value}秒", "读取失败")}")

关键注意事项

  1. GUID正确性:不同UEFI变量属于不同的GUID命名空间,大部分全局变量使用EFI_GLOBAL_VARIABLE_GUID,启动项相关变量需使用对应专属GUID;
  2. 二进制变量处理:像ErrOut这类二进制数据变量,需要根据UEFI规范定义对应的结构体进行解析,不能直接按字符串读取;
  3. 权限要求:读取UEFI变量需要管理员权限,否则函数会返回0并设置错误码ERROR_ACCESS_DENIED。

内容的提问来源于stack exchange,提问作者ElektroStudios

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 22:12:54