2017-08-31 96 views
0

我试图获得与bcdedit命令“bcdedit/enum ALL”相同的信息,但使用wmi和C#。我知道如何获取bootmgr条目(请参阅代码),但我无法获取所有条目,特别是设备选项是我正在查找的信息。有没有人有一个想法如何实现这一目标?如何使用wmi获得与bcdedit/enum ALL相同的结果?

这是我用来获取标准和传统os启动项的代码。

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])); 
+0

如果您在'ManagementObject'上使用'EnumerateElements'方法并设置断点,则可以检查结果并将其复制到您的问题中。 – Hackerman

回答

0

如果你需要学习的启动项,你有兴趣的类型值,可以使用Bcdedit.exe来查找条目的GUID,然后加载在你的程序把GUID该条目在ManagementPath像你这样的:

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

然后得到一个类型属性的这样的值:

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

在情况下,如果bcdedit.exe的节目“众所周知”的标识如{当前}或{ bootmgr},使用this document将标识符映射到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 documentation on BcdObject class

0

我找到了解决方案。几乎总是这样,它非常明显而且简单。我只是通过0x0作为类型的电话。

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该函数将返回这两个设备。

相关问题