我正在撰寫一個腳本來將現有的位鎖定密鑰備份到 Azure AD 中的關聯設備,我創建了一個函式,該函式通過啟用位鎖定的卷并將密鑰備份到 Azure 但是想知道如何檢查該功能已成功完成,沒有任何錯誤。這是我的代碼。我已經在函式中添加了一個 try and catch 以捕獲函式本身的任何錯誤但是我如何檢查函式是否已成功完成 - 目前我有一個 IF 陳述句檢查最后一個命令是否已運行“$? - 這是正確或我該如何驗證?
function Invoke-BackupBDEKeys {
##Get all current Bit Locker volumes - this will ensure keys are backed up for devices which may have additional data drives
$BitLockerVolumes = Get-BitLockerVolume | select-object MountPoint
foreach ($BDEMountPoint in $BitLockerVolumes.mountpoint) {
try {
#Get key protectors for each of the BDE mount points on the device
$BDEKeyProtector = Get-BitLockerVolume -MountPoint $BDEMountPoint | select-object -ExpandProperty keyprotector
#Get the Recovery Password protector - this will be what is backed up to AAD and used to recover access to the drive if needed
$KeyId = $BDEKeyProtector | Where-Object {$_.KeyProtectorType -eq 'RecoveryPassword'}
#Backup the recovery password to the device in AAD
BackupToAAD-BitLockerKeyProtector -MountPoint $BDEMountPoint -KeyProtectorId $KeyId.KeyProtectorId
}
catch {
Write-Host "An error has occured" $Error[0]
}
}
}
#Run function
Invoke-BackupBDEKeys
if ($? -eq $true) {
$ErrorActionPreference = "Continue"
#No errors ocurred running the last command - reg key can be set as keys have been backed up succesfully
$RegKeyPath = 'custom path'
$Name = 'custom name'
New-ItemProperty -Path $RegKeyPath -Name $Name -Value 1 -Force
Exit
}
else {
Write-Host "The backup of BDE keys were not succesful"
#Exit
}
uj5u.com熱心網友回復:
不幸的是,如PowerShell的7.2.1,在自動
$?可變具有沒有呼叫后有意義的值寫入的-PowerShell的函式(而不是一個二值小命令)。(更直接的是,即使在函式內部,也$?只反映$false在catch塊的最開始,正如 Mathias 所指出的)。如果 PowerShell 函式具有與二進制 cmdlet 相同的功能,則發出至少一個(非腳本終止)錯誤,例如 with
Write-Error,將$?在呼叫者的范圍內設定為$false,但目前情況并非如此。您可以通過使用解決此限制
$PSCmdlet.WriteError()由高級功能或腳本,但是那是相當繁瑣的。這同樣適用于$PSCmdlet.ThrowTerminatingError(),這是從 PowerShell 代碼創建陳述句終止錯誤的唯一方法。(相比之下,該throw陳述句生成一個腳本終止錯誤,即終止整個腳本及其呼叫者 - 除非try/catch或trap陳述句在呼叫堆疊的某處捕獲錯誤)。有關更多資訊和相關 GitHub 問題的鏈接,請參閱此答案。
作為一種解決方法,我建議:
使您的函式成為高級函式,以便支持公共
-ErrorVariable引數- 它允許您在自選變數中收集函式發出的所有非終止錯誤。注:自己選擇的變數名必須通過無的
$; 例如,要在變數中收集$errs,請使用-ErrorVariable errs; 不要使用Error/$Error,因為它$Error是收集整個會話中發生的所有錯誤的自動變數。您可以將它與common
-ErrorAction引數結合起來,以最初使錯誤 (-ErrorAction SilentlyContinue)靜音,以便稍后根據需要發出它們。不要使用-ErrorAction Stop,因為它會變得-ErrorVariable毫無用處,反而會中止整個腳本。
您可以讓錯誤簡單地發生 - 不需要
try/catch陳述句:由于throw您的代碼中沒有陳述句,因此即使在給定的迭代中發生錯誤,您的回圈也將繼續運行。- 注:雖然可以捕獲終止錯誤與內環路
try/catch然后轉發它們作為非終止那些用$_ | Write-Error在catch塊,你會與每個這樣的錯誤結束了兩次傳遞給變數-ErrorVariable。(如果你不中繼,錯誤仍然會被收集,但不會列印。)
- 注:雖然可以捕獲終止錯誤與內環路
呼叫后,檢查是否收集到任何錯誤,以確定是否至少有一個密鑰沒有備份成功。
順便說一句:當然,您也可以使函式輸出(回傳)布林值(
$true或$false)來指示是否發生錯誤,但這對于設計用于輸出資料的函式來說不是一個選項。
以下是這種方法的概要:
function Invoke-BackupBDEKeys {
# Make the function an *advanced* function, to enable
# support for -ErrorVariable (and -ErrorAction)
[CmdletBinding()]
param()
# ...
foreach ($BDEMountPoint in $BitLockerVolumes.mountpoint) {
# ... Statements that may cause errors.
# If you need to short-circuit a loop iteration immediately
# after an error occurred, check each statement's return value; e.g.:
# if (-not $BDEKeyProtector) { continue }
}
}
# Call the function and collect any
# non-terminating errors in variable $errs.
# IMPORTANT: Pass the variable name *without the $*.
Invoke-BackupBDEKeys -ErrorAction SilentlyContinue -ErrorVariable errs
# If $errs is an empty collection, no errors occurred.
if (-not $errs) {
"No errors occurred"
# ...
}
else {
"At least one error occurred during the backup of BDE keys:`n$errs"
# ...
}
這是一個最小的示例,它使用腳本塊代替函式:
& {
[CmdletBinding()] param() Get-Item NoSuchFile
} -ErrorVariable errs -ErrorAction SilentlyContinue
"Errors collected:`n$errs"
輸出:
Errors collected:
Cannot find path 'C:\Users\jdoe\NoSuchFile' because it does not exist.
uj5u.com熱心網友回復:
如其他地方所述,您正在使用的 try/catch 是阻止錯誤條件中繼的原因。這是設計使然,也是使用 try/catch 的有意原因。
在您的情況下,我會做的是創建一個變數或一個檔案來捕獲錯誤資訊。我向任何名為“鮑勃”的人道歉。這是我總是用于快速處理的變數名。
這是一個有效的基本示例:
$bob = (1,2,"blue",4,"notit",7)
$bobout = @{} #create a hashtable for errors
foreach ($tempbob in $bob) {
$tempbob
try {
$tempbob - 2 #this will fail for a string
} catch {
$bobout.Add($tempbob,"not a number") #store a key/value pair (current,msg)
}
}
$bobout #output the errors
在這里,我們創建了一個陣列只是為了使用 foreach。把它想象成你的 $BDEMountPoint 變數。
經歷每一個,做你想做的。在 }catch{} 中,您只想在失敗時說“不是數字”。這是它的輸出:
-1
0
2
5
Name Value
---- -----
notit not a number
blue not a number
所有的數字都有效(你可以明顯地抑制輸出,這只是為了演示)。更重要的是,我們在失敗時存盤了自定義文本。
現在,您可能需要更多資訊錯誤。您可以抓住這樣發生的實際錯誤:
$bob = (1,2,"blue",4,"notit",7)
$bobout = @{} #create a hashtable for errors
foreach ($tempbob in $bob) {
$tempbob
try {
$tempbob - 2 #this will fail for a string
} catch {
$bobout.Add($tempbob,$PSItem) #store a key/value pair (current,error)
}
}
$bobout
這里我們使用了當前被檢查的變數$PSItem,通常也被稱為$_。
-1
0
2
5
Name Value
---- -----
notit Cannot convert value "notit" to type "System.Int32". Error: "Input string was not in ...
blue Cannot convert value "blue" to type "System.Int32". Error: "Input string was not in a...
您還可以決議實際錯誤并根據它采取措施或存盤自定義訊息。但這超出了這個答案的范圍。:)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/405515.html
標籤:
上一篇:陣列行索引函式
