Как получить тот же результат, что и при использовании bcdedit /enum ALL с помощью wmi?

Я пытаюсь получить ту же информацию, что и с помощью команды bcdedit «bcdedit /enum ALL», но с помощью wmi и C#. Я знаю, как получить записи bootmgr (см. код), но я не могу получить все записи, особенно параметры устройства — это информация, которую я ищу. Кто-нибудь знает, как этого добиться?

Это код, который я использую для получения стандартных и устаревших загрузочных записей ОС.

    public class BCDWMI
{
    public static readonly UInt32 BCDE_STANDARD_OS_ENTRY = 0x10200003;
    public static readonly UInt32 BCDE_LEGACY_OS_ENTRY = 0x10300006;
    public static readonly UInt32 BcdLibraryElementTypeString_Description = 0x12000004;

    public static Dictionary<string, string> EnumerateObjectsByType(uint bcdType, string storePath)
    {

        Dictionary<string, string> dictEntries = null;

        ConnectionOptions options = new ConnectionOptions();
        options.Impersonation = ImpersonationLevel.Impersonate;
        options.EnablePrivileges = true;
        ManagementScope MgmtScope = new ManagementScope("root\\WMI", options);
        ManagementPath MgmtPath = new ManagementPath("root\\WMI:BcdStore.FilePath='" + storePath + "'");
        ManagementObject bcdStore = new System.Management.ManagementObject(MgmtScope, MgmtPath, null);
        ManagementBaseObject[] mboArray;

        bool success = EnumerateObjects(bcdStore, bcdType, out mboArray);
        if (success)
        {
            dictEntries = new Dictionary<string, string>();

            foreach (ManagementBaseObject mbo in mboArray)
            {
                ManagementPath BcdObjectPath = new ManagementPath("root\\WMI:BcdObject.Id=\"" + mbo.GetPropertyValue("Id") + "\",StoreFilePath='" + storePath + "'");

                ManagementObject BcdObject = new ManagementObject(MgmtScope, BcdObjectPath, null);
                ManagementBaseObject Element;
                String Description = String.Empty;
                try
                {
                    bool getDescripStatus = GetElement(BcdObject, BcdLibraryElementTypeString_Description, out Element);
                    if (getDescripStatus)
                        Description = Element.GetPropertyValue("String").ToString();
                }
                catch (Exception)
                {
                }
                dictEntries.Add((string)mbo.GetPropertyValue("Id"), String.Format("Type: {0:X8} {1}", mbo.GetPropertyValue("Type"), Description));
            }
        }
        return dictEntries;
    }

    public static bool EnumerateObjects(ManagementObject bcdStore, uint Type, out System.Management.ManagementBaseObject[] Objects)
    {
        System.Management.ManagementBaseObject inParams = null;
        inParams = bcdStore.GetMethodParameters("EnumerateObjects");
        inParams["Type"] = ((uint)(Type));
        System.Management.ManagementBaseObject outParams = bcdStore.InvokeMethod("EnumerateObjects", inParams, null);
        Objects = ((System.Management.ManagementBaseObject[])(outParams.Properties["Objects"].Value));
        return System.Convert.ToBoolean(outParams.Properties["ReturnValue"].Value);
    }

    public static bool GetElement(ManagementObject bdcObject, uint Type, out System.Management.ManagementBaseObject Element)
    {
        System.Management.ManagementBaseObject inParams = null;
        inParams = bdcObject.GetMethodParameters("GetElement");
        inParams["Type"] = ((uint)(Type));
        System.Management.ManagementBaseObject outParams = bdcObject.InvokeMethod("GetElement", inParams, null);
        Element = ((System.Management.ManagementBaseObject)(outParams.Properties["Element"].Value));
        return System.Convert.ToBoolean(outParams.Properties["ReturnValue"].Value);
    }
}

Чтобы запросить системное хранилище, я вызываю функцию следующим образом.

            Dictionary<string, string> StdOSEntries = BCDWMI.EnumerateObjectsByType(BCDWMI.BCDE_STANDARD_OS_ENTRY, String.Empty);
        foreach (String guid in StdOSEntries.Keys)
            Debug.WriteLine(String.Format("Id={0} {1}", guid,  StdOSEntries[guid]));

person Luzius    schedule 31.08.2017    source источник
comment
Если вы используете метод EnumerateElements на своем ManagementObject и устанавливаете точку останова, вы можете проверить результат и скопировать его в свой вопрос, пожалуйста.   -  person Hackerman    schedule 31.08.2017


Ответы (2)


Если вам нужно узнать значение типа интересующей вас загрузочной записи, вы можете использовать bcdedit.exe для поиска GUID этой записи, а затем загрузить эту запись в свою программу, поместив GUID в ManagementPath, как вы это делаете:

ManagementPath BcdObjectPath = new ManagementPath("root\\WMI:BcdObject.Id=\"" + "{Guid goes here}" + "\",StoreFilePath='" + storePath + "'");

затем получите значение свойства Type следующим образом:

uint Type = (uint)BcdObject["Type"];
Console.WriteLine("{0:X8}", Type);

Если bcdedit.exe показывает «известный» идентификатор, например {current} или {bootmgr}, используйте этот документ, чтобы сопоставить идентификатор с GUID.

Вы также можете программно перечислить типы следующим образом:

for (uint a = 1; a <= 10; a++) {
    uint FirmwareType = 0x10100000 | a;
    uint BootType = 0x10200000 | a;
    uint LegacyType = 0x10300000 | a;
    uint RealModeType = 0x10400000 | a;
}

который даст идентификаторы, как у вас здесь

public static readonly UInt32 BCDE_STANDARD_OS_ENTRY = 0x10200003;
public static readonly UInt32 BCDE_LEGACY_OS_ENTRY = 0x10300006;

См. документацию WMI по классу BcdObject для описания того, как формируются эти идентификаторы.

person krendelj    schedule 14.09.2017

Я нашел решение. Как почти всегда, это довольно очевидно и просто. Я только что передал 0x0 как Type для вызова.

Dictionary<string, string> StdOSEntries = BCDWMI.EnumerateObjectsByType(0, String.Empty);

И это то, что я получаю.

    Id: {0ce4991b-e6b3-4b16-b23c-5e0d9250e5d9} Type: 20100000 
Id: {4636856e-540f-4170-a130-a84776f4c654} Type: 20100000 
Id: {6efb52bf-1766-41db-a6b3-0ee5eff72bd7} Type: 20200003 
Id: {7619dcc8-fafe-11d9-b411-000476eba25f} Type: 30000000 
Id: {7619dcc9-fafe-11d9-b411-000476eba25f} Type: 10200003 Windows Setup 
Id: {7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e} Type: 20100000 
Id: {7ff607e0-4395-11db-b0de-0800200c9a66} Type: 20200003 Hypervisor Settings
Id: {9dea862c-5cdd-4e70-acc1-f32b344d4795} Type: 10100002 Windows Boot Manager
Id: {a19f4228-8f0e-11e7-ac85-005056c00008} Type: 30000000 
Id: {a1c5dee9-8f0e-11e7-ac85-005056c00008} Type: 10200003 WinPE x86
Id: {a20de869-8f0e-11e7-ac85-005056c00008} Type: 10200003 WinPE amd64
Id: {b2721d73-1db4-4c62-bf78-c548a880142d} Type: 10200005 Windows Memory Diagnostic

Параметры моего устройства теперь перечислены с типом 0x30000000. Поэтому, если я передам 0x30000000, функция вернет два устройства.

person Luzius    schedule 18.09.2017