2017-08-31 137 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該函數將返回這兩個設備。

相關問題