none
How to get Boot Configuration Data (BCD) Information out of WMI with PowerShell? RRS feed

  • Question

  • I can't for the life of me figure out how to access BCD information (for those of you that don't know, BCD replaced boot.ini in Windows Vista/7/W2K8) via PowerShell. This seems possible via WMI, but I'm am having no luck figuring out how to access root\wmi and the BCD* classes. I found some VBScript examples, but I have been unable to translate any of these into their appropriate PowerShell equivalents. I'm hoping someone can post some working examples. Specifically, I'm trying to determine the DEP setting and the boot timeout for a remote computer.

    One of the examples I found looks promising:

    set Locator = CreateObject("WbemScripting.SWbemLocator")
    set Services = Locator.ConnectServer(".", "root\wmi")
    Services.Security_.ImpersonationLevel = 3
     
    DefaultOsIdentifier = WScript.Arguments(0)
     
    'These hardcoded values will be replaced with official constants
    ' whenavailable.
     
    const BootMgrId = "{9dea862c-5cdd-4e70-acc1-f32b344d4795}"
    const DefaultType = &h23000003
    '
    'Open up a connection to WMI BcdStore class, allowing for
    'impersonation. We need to request that Backup and Restore
    'privileges be granted as well.
     
    set BcdStoreClass = GetObject("winmgmts:{impersonationlevel=impersonate,(Backup,Restore)}!" & MachineName & "root/wmi:BcdStore")
     
    if not BcdStoreClass.OpenStore("", BcdStore) then
      WScript.Echo "Couldn't open the system store!"
      WScript.Quit
    end if
    '
    ' Open the "boot manager" object.
    '
    if not BcdStore.OpenObject(BootMgrId, BootMgr) then
      WScript.Echo "Couldn't open the boot manager object!"
      WScript.Quit
    end if
    '
    ' Set the boot manager's default OS object to the specified OS.
    ' Note that objects must be passed as strings.
    '
    if not BootMgr.SetObjectElement(DefaultType, DefaultOSIdentifier) then
      WScript.Echo "Couldn't set the default OS value!"
      WScript.Quit
    end if
     
    WScript.Echo "Successfully set the boot manager's default OS value."
    

    But I can't seem to figure out how to use BcdStore to get to BootMgr. I keep getting "Provider is not capable of the attempted operation" or other errors. I also don't quite understand when to use Get-WmiObject vs. Invoke-WmiMethod. I've always used the former for Win32_* classes.

    PS H:\> (Get-WmiObject -Namespace "root\wmi" -Class BcdStore -Impersonation 3).OpenStore()
    Get-WmiObject : Provider is not capable of the attempted operation
    At line:1 char:15
    + (Get-WmiObject <<<< -Namespace "root\wmi" -Class BcdStore -Impersonation 3).OpenStore()
      + CategoryInfo     : InvalidOperation: (:) [Get-WmiObject], ManagementException
      + FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
    
    You cannot call a method on a null-valued expression.
    At line:1 char:81
    + (Get-WmiObject -Namespace "root\wmi" -Class BcdStore -Impersonation 3).OpenStore <<<< ()
      + CategoryInfo     : InvalidOperation: (OpenStore:String) [], RuntimeException
      + FullyQualifiedErrorId : InvokeMethodOnNull
    
    
    PS H:\> Invoke-WmiMethod -Class BcdStore -ComputerName XA601-010 -Namespace root\wmi -Name OpenStore("", $bcdStore)
    
    __GENUS     : 2
    __CLASS     : __PARAMETERS
    __SUPERCLASS   :
    __DYNASTY    : __PARAMETERS
    __RELPATH    :
    __PROPERTY_COUNT : 2
    __DERIVATION   : {}
    __SERVER     :
    __NAMESPACE   :
    __PATH      :
    ReturnValue   : True
    Store      : System.Management.ManagementBaseObject
    
    PS H:\> $bcdStore
    PS H:\>
    


    Thanks in advance,

    Jason

    Wednesday, June 15, 2011 3:54 PM

Answers

  • Start here:

    $bcdStore=gwmi -name root\wmi -list bcdstore -enableall
    $bcdStore|gm

    $result=$bcdStore.OpenStore("") # can also use explicit file name.
    $store=$result.Store


    jv
    Wednesday, June 15, 2011 10:02 PM

All replies

  • Start here:

    $bcdStore=gwmi -name root\wmi -list bcdstore -enableall
    $bcdStore|gm

    $result=$bcdStore.OpenStore("") # can also use explicit file name.
    $store=$result.Store


    jv
    Wednesday, June 15, 2011 10:02 PM
  • Thanks for this start.

    But further steps are required to enumerate or open some BCD Objects.

    If I got right the BCD WMI Provider documentation (http://msdn.microsoft.com/en-us/library/windows/desktop/aa362677(v=vs.85).aspx) and some sample codes in vbs, with OpenStore I got an instance of the bcdstore. And this object should got some methods like "EnumerateObjects" or "OpenObject". But in Powershell I'm not able to call or see any of this methods.

    Any help is appreciate and thanks in advance.

    Friday, July 27, 2012 11:25 AM
  • Very easy:

    $store=gwmi -name root\wmi -li bcdstore 
    $store.OpenStore("")
    ($store.GetSystemDisk()).Disk
    $store.psbase.methods|select name


    ¯\_(ツ)_/¯

    Friday, July 27, 2012 12:29 PM
  • At first, thanks for your support, jrv.

    I'm sorry. I guess my question wasn't clear enough.
    I don't know how to manipulate the BCD.

    For example the same in vbs here (http://technet.microsoft.com/en-us/magazine/2008.07.heyscriptingguy.aspx?pr=PuzzleAnswer):

    Set objStoreClass = GetObject("winmgmts:{(Backup,Restore)}\\" & strComputer & "\root\wmi:BcdStore") objStoreClass.OpenStore "", objStore objStore.OpenObject Current, objDefault"

    I thought "Easy in Powershell":

    $store=gwmi -name root\wmi -li bcdstore;
    (or another of many beginnings: $
    store = ([WMIClass]"Root\WMI:BcdStore").OpenStore(""); $store.OpenStore("");
    $store.OpenObject("Current");

    And the last line produced the error:
    Method invocation failed because [System.Management.ManagementClass#ROOT\wmi\BcdStore] doesn't contain a method named '
    OpenObject'.

    So, where am I wrong? And why do I see the needed methos in the base methods?

    Thanks again advanced.

    Friday, July 27, 2012 4:41 PM
  • If you just want to read teh store then use this:
    invoke-command {bcdedit /v} -comp ws101


    ¯\_(ツ)_/¯

    Friday, July 27, 2012 6:52 PM
  • I don't want just to read the store. I got to enable and configure the settings of ems in an automatic way.
    We are using many languages in Windows. Therefore parsing the bcdedit output is not a solution.

    Since I don't know which identifier are present in the store, I got to iterate the existing objects (some computers are using software raid and both should be able to boot with ems support).Then, knowing the identifier, I should be able to do my work. So, my thought was that the wmi provider for bcd should solve my issue.

    Thanks again.

    Saturday, July 28, 2012 12:01 PM
  • It works with VBScript.  Use VBScript to manage the settings.  You can call VBScript functions from PowerShell if needed.

    The WMI method calls fail with POwerSHell because the interfaces to Te BCD components have been implemented in a very strange way.  I have tried repeatedly to get the store to instantiate.  It will in VBScript and not in PowerShell.

    You can also use C# and VB.NET from the examples in the SDK.

    If this is critical to your operation then you may be forced to read and set things using BCDEdit.  This works so you are not being prevented from doing your work.  You can read everything in the store and you can set everything in the store.

    If you absolutely can only do it using WMI from PowerShell then I suggest posting in the Windows management forum.  Someone there might know if this is possible.


    ¯\_(ツ)_/¯

    • Proposed as answer by Basti78 Saturday, July 28, 2012 2:42 PM
    Saturday, July 28, 2012 2:02 PM
  • Thanks, thanks, thanks. I doubt in me already. But your confirmation helps me :)

    Now, I'll do it in C#. But nevertheless, to get clearness, I will ask this question in the Windows Management Forum.

    Thank you jrv!!!

    Saturday, July 28, 2012 2:47 PM
  • You will have the exact same issues in C# unless you sue the SDK example and call the API directly.  This will drastically limit your ability to use this API remotely.

    The SDK has a complete VBS script that fully emulated the BCDEdit functionality.  Also, It hit me to use COM from POwerShell.  This is very convoluted unless you know COM and how to poke at it from COM and WMI primitives.  Basically we have to use the ExecMethod_ of the WMI object to call all methods along with manually setting up the paramaters.

    Here is an example of a working script in PowerShell that does what "The Scritping Guys Blog" article did. Give it a go.

    # constants
    $BcdLibraryString_Description = 0x12000004
    $WindowsImages = 0x10200003
    $LegacyImages = 0x10300006
    $server='.'
    #
    $locator= New-Object -ComObject WbemScripting.SWbemLocator
    $locator.Security_.Privileges.AddAsString('SeBackupPrivilege')
    $locator.Security_.Privileges.AddAsString('SeRestorePrivilege')
    #
    #
    $wmi=$locator.ConnectServer($server,'root\wmi')
    $class = $wmi.Get("BcdStore")
    #
    # - Build parameter object and call "OpenStore" method
    $inparams=$class.Methods_.Item('OpenStore').InParameters.SpawnInstance_()
    $inparams.Properties_.Item('File').Value=''
    $outParams=$class.ExecMethod_('OpenStore',$inparams)
    if($outParams.Properties_.Item('ReturnValue').Value){
        #
        Write-Host 'Opened default store successful' -ForegroundColor green
        $store=$outParams.Properties_.Item('Store').Value
        #
        # enumerate images
        $inparams=$store.Methods_.Item('EnumerateObjects').InParameters.SpawnInstance_()
        $inparams.Properties_.Item('Type').Value=$WindowsImages
        $outParams=$store.ExecMethod_('EnumerateObjects',$inparams)
        if($outParams.Properties_.Item('ReturnValue').Value){
            Write-Host '"EnumerateObjects  successful' -ForegroundColor green
            $images=$outParams.Properties_.Item('Objects').Value
            $images|%{$_.Properties_|?{$_.Name -eq 'Id'}}|select Name,Value
        }else{
            Write-Host 'Get objects Windows Images failed' -fore red
        }
    }else{
        Write-Host 'Store could not be opened' -ForegroundColor red
    }
    #

    The method call could be generalized with named parameters to make it easier.

    This technique can return and set all of the values in the BCD store. 

    If I feel motivated this week I may complete the code as a module although I do not see it as a big priority.  For those who may the above is my contribution to their solution.


    ¯\_(ツ)_/¯




    • Edited by jrv Sunday, July 29, 2012 2:40 PM
    • Proposed as answer by Basti78 Monday, July 30, 2012 8:19 AM
    Sunday, July 29, 2012 2:27 PM
  • Thanks again jrv. You did it. Without you I was stuck in this dead end street.
    Monday, July 30, 2012 8:21 AM
  • If you need more help with this then please start a new thread as the original purpose for this thread has bee more than satisfied.


    ¯\_(ツ)_/¯

    Monday, July 30, 2012 9:52 AM