简体   繁体   English

如何检测 WinPE(4) 是否已从 UEFI 或 BIOS 启动?

[英]How do I detect if WinPE(4) has booted from a UEFI or BIOS?

I am looking for a way to reliably detect when I boot into WinPE 4 (powershell) ( or WinPE 3 (vbs) as an alternative ), have I booted from a UEFI or BIOS System?我正在寻找一种方法来可靠地检测何时我启动到WinPE 4 (powershell)或 WinPE 3 (vbs) 作为替代),我是从 UEFI 或 BIOS 系统启动的吗? ( without running a third party exe as I am in a restricted environment ) 因为我在受限环境中,所以没有运行第三方 exe

This significantly changes how I would be partitioning a windows deployment as the partitions layout changes and format.随着分区布局和格式的变化,这显着改变了我对 Windows 部署进行分区的方式。 (GPT vs. MBR, etc) (GPT 与 MBR 等)

I have one working that is an adaptation of this C++ code in powershell v3 but it feels pretty hack-ish :我有一个工作是在 powershell v3 中改编这个 C++代码,但感觉很hack-ish:

## Check if we can get a dummy flag from the UEFI via the Kernel
## [Bool] check the result of the kernel's fetch of the dummy GUID from UEFI
## The only way I found to do it was using the C++ compiler in powershell
Function Compile-UEFIDectectionClass{
    $win32UEFICode= @'
    using System;
    using System.Runtime.InteropServices;

    public class UEFI
    {
       [DllImport("kernel32.dll")]
       public static extern UInt32 GetFirmwareEnvironmentVariableA([MarshalAs(UnmanagedType.LPWStr)] string lpName, [MarshalAs(UnmanagedType.LPWStr)] string lpGuid, IntPtr pBuffer, UInt32 nSize); 

       public static UInt32 Detect()
       {
            return GetFirmwareEnvironmentVariableA("", "{00000000-0000-0000-0000-000000000000}", IntPtr.Zero, 0);
       }
    }
    '@

Add-Type $win32UEFICode
}


## A Function added just to check if the assembly for 
## UEFI is loaded as is the name of the class above in C++.
Function Check-IsUEFIClassLoaded{
     return ([System.AppDomain]::CurrentDomain.GetAssemblies() | % { $_.GetTypes()} | ? {$_.FullName -eq "UEFI"}).Count 
}

## Just incase someone was to call my code without running the Compiled code run first
If (!(Check-IsUEFIClassLoaded)){
    Compile-UEFIDectectionClass
}

## The meat of the checking.
## Returns 0 or 1 ([BOOL] if UEFI or not)
Function Get-UEFI{
    return [UEFI]::Detect()
}

This seems pretty over the top just to get a simple flag.为了获得一个简单的标志,这似乎太过分了。

Does anyone know if there is there a better way to get this done?有谁知道是否有更好的方法来完成这项工作?

It is no less hacky, in the sense it will still require interop from powershell, but the interop code might be neater if you use (or can call): GetFirmwareType() .从某种意义上说,它仍然需要来自 powershell 的互操作,但如果您使用(或可以调用): GetFirmwareType() ,则互操作代码可能会更简洁。

This returns a FIRMWARE_TYPE enumeration documented here .这将返回此处记录的FIRMWARE_TYPE枚举。 I can't believe given both functions are introduced in Windows 8 and exported by kernel32.dll that Microsoft's own documentation points you at "using a dummy variable"!我不敢相信这两个函数都是在 Windows 8 中引入并由 kernel32.dll 导出的,Microsoft 自己的文档将您指向“使用虚拟变量”!

Internally, GetFirmwareType calls NtQuerySystemInformation .在内部, GetFirmwareType调用NtQuerySystemInformation I will dig into what it is doing, but I do not think it is necessarily going to be enlightening.我将深入研究它在做什么,但我认为它不一定会具有启发性。

Unfortunately, this only works for PE4 (Windows 8) since these functions were only added then.不幸的是,这仅适用于 PE4 (Windows 8),因为这些功能只是那时才添加的。

到目前为止,最简单的方法是在 PowerShell 上运行:

$(Get-ComputerInfo).BiosFirmwareType

这可能有点晚了,但如果知道它们在 WinPE 中运行,则以下代码应该可以工作:

$isuefi = (Get-ItemProperty -Path HKLM:\System\CurrentControlSet\Control).PEFirmwareType -eq 2

I've have no UEFI system to test it on, but this article seems to imply there's a registry value you can query under PE to tell what mode it was booted under: 我没有UEFI系统来测试它,但是本文似乎暗示有一个注册表值,你可以在PE下查询它,告诉它在什么模式下启动:

http://technet.microsoft.com/en-us/library/dn293283.aspx http://technet.microsoft.com/en-us/library/dn293283.aspx

$env:firmware_type

Not sure since what version this is supported.不确定从哪个版本开始支持。 Returns UEFI and Legacy in my tests.在我的测试中返回UEFILegacy

However this is on full installation, Have note confirmed existence in WinPE但是,这是完全安装,请注意确认 WinPE 中存在

It looks like the PE environment has a folder that is specific to the PE environment.看起来PE环境有一个特定于PE环境的文件夹。 In addition, the variable %TargetDir% is described here, TARGETDIR property .此外,此处描述了变量 %TargetDir%, TARGETDIR 属性

Lastly, you could check if you are running from X: There should be also a folder that has the boot.wim image you can check for.最后,您可以检查您是否正在从 X 运行:应该还有一个文件夹,其中包含您可以检查的 boot.wim 映像。 I believe the path would be X:\\Sources\\Boot.wim but double check.我相信路径是X:\\Sources\\Boot.wim但请仔细检查。

if ( Test-Path "%TargetDir%\Windows\wpeprofiles" ) {

     Write-host "You're in Windows PE"

}

I don't know if this will help (based on C# solution), but:我不知道这是否会有所帮助(基于 C# 解决方案),但是:

Win32_DiskPartition has the properties "Bootable" (bool), "BootPartition" (bool), and "Type" (string). Win32_DiskPartition 具有属性“Bootable”(bool)、“BootPartition”(bool)和“Type”(字符串)。 For my UEFI system, "Type" comes back as the string "GPT: System".对于我的 UEFI 系统,“类型”作为字符串“GPT:系统”返回。

Now, for all Win32_DiskPartitions that are bootable, are a boot partition, and have the specified type, determine if any of them are internal.现在,对于所有可引导、是引导分区并具有指定类型的 Win32_DiskPartitions,确定它们中是否有任何是内部的。

Hope this helps.希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM