Search code examples
c#windows-7wmibcdeditbcdstore

Access the Windows 7 Boot Configuration Data using C#


I need to be able to access the identifier GUID of the current running installation of Windows from the Boot Configuration Data Store using c#. It can be returned from the command line running:

bcdedit /enum {current} /v

The problem I have is that in c# if I try to directly run this command (even though the program is running as Administrator) I'm told that bcdedit does not exist. I'm using:

ProcessStartInfo procStartInfo = new ProcessStartInfo("bcdedit.exe", "/enum {current} /v");

The other thing that I have researched is using WMI but the only reference I have to doing so is http://msdn.microsoft.com/en-us/library/windows/desktop/aa362673(v=vs.85).aspx which isn't very helpful.

The best solution would be if I don't have to use bcdedit but instead could use native WMI classes. How would I find the current Windows Boot Loader identifier using C#?


Solution

  • There seem to be many problems accessing bcdedit.exe directly but I was able to figure out how to use WMI in C# to access the BcdStore:

    ConnectionOptions connectionOptions = new ConnectionOptions();
    connectionOptions.Impersonation = ImpersonationLevel.Impersonate;
    connectionOptions.EnablePrivileges = true;
    
    // The ManagementScope is used to access the WMI info as Administrator
    ManagementScope managementScope = new ManagementScope(@"root\WMI", connectionOptions);
    
    // {9dea862c-5cdd-4e70-acc1-f32b344d4795} is the GUID of the System BcdStore
    ManagementObject privateLateBoundObject = new ManagementObject(managementScope, new ManagementPath("root\\WMI:BcdObject.Id=\"{9dea862c-5cdd-4e70-acc1-f32b344d4795}\",StoreFilePath=\"\""), null);
    
    ManagementBaseObject inParams = null;
    inParams = privateLateBoundObject.GetMethodParameters("GetElement");
    
    // 0x24000001 is a BCD constant: BcdBootMgrObjectList_DisplayOrder
    inParams["Type"] = ((UInt32)0x24000001);
    ManagementBaseObject outParams = privateLateBoundObject.InvokeMethod("GetElement", inParams, null);
    ManagementBaseObject mboOut = ((ManagementBaseObject)(outParams.Properties["Element"].Value));
    
    string[] osIdList = (string[]) mboOut.GetPropertyValue("Ids");
    
    // Each osGuid is the GUID of one Boot Manager in the BcdStore
    foreach (string osGuid in osIdList)
    {
        ManagementObject currentManObj = new ManagementObject(managementScope, new ManagementPath("root\\WMI:BcdObject.Id=\"" + osGuid + "\",StoreFilePath=\"\""), null);
                MessageBox.Show("" + currentManObj.GetPropertyValue("Id"));
    }
    

    This gets the GUID of every Windows Boot Manager in the BcdStore and shows them in a MessageBox. It should be noted that you must have the right ConnectionOptions and that this program must be run as Administrator.

    Thanks to Ross Johnston for his project at: http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=18233 to find the BCD constants and to Tran Dinh Hop for his project at: http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=19208 which has all of the C# code to work with the BcdStore (except for the aforementioned constants).

    Update:

    Using:

    ManagementObject privateLateBoundObject = new ManagementObject(managementScope, new ManagementPath("root\\WMI:BcdObject.Id=\"{fa926493-6f1c-4193-a414-58f0b2456d1e}\",StoreFilePath=\"\""), null);
    

    will obtain the BcdObject for the current, running Windows Boot Manager. If you then call:

    currentManObj.GetPropertyValue("Id")
    

    you will get the GUID of the current, running Windows Boot Manager which is different from "{fa926493-6f1c-4193-a414-58f0b2456d1e}" which is a link to the current Boot Manager.

    Thanks to The Microsoft Scripting Guys and their project at: http://technet.microsoft.com/en-us/magazine/2008.07.heyscriptingguy.aspx?pr=blog for having that GUID constant that links to the current Boot Manager.