2013-06-03 31 views
2

這樣我就可以在PowerShell腳本中寫BCD命令,如果我是在命令提示符,例如:BCDEDIT,bcdstore和PowerShell

bcdedit /default '{current}' 

不過,我需要一個腳本,做這樣的:

bcdedit /default '{current}' 
bcdedit /set '{otherboot}' description "my description" 

,如果它沒有這樣做,這將是周圍的其他方法:

bcdedit /default '{otherboot}' 
bcdedit /set '{current}' description "my description" 

什麼,我需要做的是找到T的標識他在PowerShell中的其他啓動,我不知道如何。所有的谷歌搜索都這樣做:

$bcdStore=gwmi -name root\wmi -list bcdstore -enableall 
$bcdStore|gm 
$result=$bcdStore.OpenStore("") # can also use explicit file name. 
$store=$result.Store 

但我不知道如何使用存儲一旦我有它,這似乎有點太複雜。我的意思是應該有一個更簡單的方法...不是?

回答

5

我不知道的方式與WMI做到這一點,但你可以結合使用bcdeditSelect-String

$otherboot = bcdedit /enum | 
    Select-String "path" -Context 2,0 | 
    ForEach-Object { $_.Context.PreContext[0] -replace '^identifier +' } | 
    Where-Object { $_ -ne "{current}" } 

說明:

bcdedit /enum輸出看起來大致是這樣的:

Windows Boot Manager 
-------------------- 
identifier    {bootmgr} 
device     partition=\Device\HarddiskVolume1 
description    Windows Boot Manager 
locale     en-US 
... 

Windows Boot Loader 
------------------- 
identifier    {current} 
device     partition=C: 
path     \Windows\system32\winload.exe 
description    Windows 7 
locale     en-US 
... 

Windows Boot Loader 
------------------- 
identifier    {e0610d98-e116-11e1-8aa3-e57ee342122d} 
device     partition=C: 
path     \Windows\system32\winload.exe 
description    DebugEntry 
locale     en-US 
... 

此輸出的相關部分是Windows Boot Loader部分,其中–  不像Windows Boot Manager部分  –有path記錄。因此,我們可以利用這個紀錄只選擇Windows Boot Loader部分:

Select-String "path" 

由於identifier記錄是path記錄之前2行,我們需要2線PreContext(沒有PostContext):

Select-String "path" -Context 2,0 

現在我們從bcdedit /enum的輸出中選出下面兩個塊:

identifier    {current} 
device     partition=C: 
path     \Windows\system32\winload.exe
identifier    {e0610d98-e116-11e1-8aa3-e57ee342122d} 
device     partition=C: 
path     \Windows\system32\winload.exe

既然我們只在PreContext的第一行感興趣,我們選擇使用ForEach-Object環這兩條線:

ForEach-Object { $_.Context.PreContext[0] } 

從而降低兩個塊這樣:

identifier    {current}
identifier    {e0610d98-e116-11e1-8aa3-e57ee342122d}

從中我們刪除類別(identifier)通過字符串替換:

ForEach-Object { $_.Context.PreContext[0] -replace '^identifier +' } 

正則表達式'^identifier +'匹配以單詞「identifier」開頭的(子)字符串,後跟一個或多個用空字符串替換的空格。該更換後兩個塊減少到這一點:

{current}
{e0610d98-e116-11e1-8aa3-e57ee342122d}

所以,現在我們只需要過濾掉含有{current},什麼剩下的塊是其他引導記錄的標識:

Where-Object { $_ -ne "{current}" } 

之後,變量$otherboot包含非當前引導記錄的標識符。

+0

好了,這是接近,但它不會做我想做的,如果我在這一行中插入$測試,像這樣: | %{$ test = $ _。Context.PreContext [0] -replace'^ identifier +'}' $ test實際上是{current},我用上下文編號玩弄,我試着選擇字符串「identifier」這並沒有幫助。我不完全理解這裏發生了什麼。 它看起來像我正在循環每次啓動並試圖找到標識符?我對嗎?我不一定要替換它。如果我可以使$ test =另一個啓動標識符,那麼我可以寫: bcedit/default $ test – dwarf

+0

你做錯了。請參閱最新答案中的解釋。 –

0

我知道這不是一個完整的答案,但它可能足以讓你開始。下面的代碼輸出BCD知道的所有操作系統的顯示名稱。

$cxOptions= new-object System.Management.ConnectionOptions 
$cxOptions.Impersonation=[System.Management.ImpersonationLevel]::Impersonate 
$cxOptions.EnablePrivileges=$true 

$mgmtScope=new-object System.Management.ManagementScope -ArgumentList "root\WMI",$cxOptions 
$mgmtPath=new-object System.Management.ManagementPath -ArgumentList 'root\WMI:BcdObject.Id="{9dea862c-5cdd-4e70-acc1-f32b344d4795}",StoreFilePath=""' 
$mgmtObject=new-object System.Management.ManagementObject -ArgumentList $mgmtScope,$mgmtPath,$null 

# Determine what elements exist in the object and output their value in HEX format 
#$mgmtObject.EnumerateElementTypes().types | % { "{0:X0}" -f $_ } 

$objBCD=$mgmtObject.GetElement(0x24000001) 
$objElements=$objBCD.GetPropertyValue("Element") 

$strOldID="{9dea862c-5cdd-4e70-acc1-f32b344d4795}" 
for ($i=0; $i -lt $objElements.Ids.Count; $i++) { 
    $mgmtPath.Path=$mgmtPath.Path.Replace($strOldID,$objElements.Ids[$i]) 
    $strOldID=$objElements.Ids[$i] 
    $objBCDId=new-object System.Management.ManagementObject -ArgumentList $mgmtScope,$mgmtPath,$null 
    $strOS=$objBCDId.GetElement(0x12000004) 
    $strOS.Element.String 
}