2017-06-08 61 views
1

我正在使用一個包裝腳本來調用一個函數,該函數查詢指定服務器中的某些數據庫並將元數據插入到單獨服務器上的特定數據庫。我使用$ error.count變量來確定腳本是否成功。我預計會發生一些許可/提取錯誤,並希望這些被發現並被忽略($ error.count變量沒有增加,但在作業日誌中寫有警告)。我可以確認一個權限錯誤正在發生,並且正在被正確捕獲。 $ error.count變量不會增加,但會從顯示無法訪問的數據庫的catch中打印警告。在PowerShell中捕獲級聯錯誤

我的問題發生在提取/插入功能完成運行後。緊接着這個函數返回到包裝腳本後,我再次打印$ error.count變量。這一次,它返回一個1,就像以前的錯誤將級聯放入包裝腳本中一樣。正如我前面提到的,我不希望這包括在錯誤計數中。我不知道如何或爲什麼$ error.count從這個函數中增加。

我應該使用不同的變量來確定腳本「失敗」還是不?是否有一些潛在的原因,爲什麼$ error.count會在錯誤被捕獲後不增加錯誤的函數之外增加而不增加?任何關於這個問題的指導將不勝感激。

代碼以供參考: 包裝函數:

$errorCount = $error.count 
    Write-Warning ("$errorCount Before function") 
    Extraction/Insertion_Function -serverList $serverList -insertionDB $insertionDB -ErrorAction SilentlyContinue 
    $errorCount = $error.count 
    Write-Warning ("$errorCount After function") 
    } catch { 
    Write-Error "Error caught by wrapper: $_" 
    } 

提取/ Insertion_Function:

ForEach ($db in $dbList) { 
Write-Warning "$errorCount database 
. 
. 
. 
    try { 
      $totalProperties = Get-ServerDBMetadata -DBConnectionString ($connStr) -DatabaseName $dbName -EA SilentlyContinue 
      } catch { 
       Write-Warning "Unable to extract metadata from $dbname in $server" 
       } 
} 

然後我有錯誤計數,其提取在循環內打印出/從每個數據庫中插入的元數據到插入數據庫以及包含數據庫的每個服務器的循環中:

WARNING: 0 Before function 
WARNING: 0 database 
. 
. 
. 
WARNING: 0 database 
WARNING: Unable to extract metadata from *database* in *server* 
WARNING: 0 database 
. 
. 
. 
WARNING: 0 database 
**WARNING: 1 After function** 

錯誤(權限問題)在函數內部被捕獲,但級聯到我的包裝腳本。我希望忽略這個特定的錯誤,而不忽略其他更嚴重的錯誤(如無法連接到我將元數據插入的服務器),因此將-EA忽略包裝腳本中的驅動程序函數忽略題。

+0

這裏沒有足夠的代碼來確定你在做什麼。請提供[mcve]。有一件事你應該知道,'$ error.Count'不是一個變量。 '$ error'是一個(特殊)變量,它是一個包含所有錯誤的數組,所以'$ error.Count'顯示了數組的大小。 '$ error'追加到開頭,而不是結尾,所以'$ error [0]'總是最新的錯誤。如果你想知道爲什麼計數正在增加,那麼在調用之前和之後查看'$ error [0]',因爲實際的錯誤會給你提供線索。 – briantist

+0

我知道發生了什麼事。它是一個許可問題。我的問題是我想忽略這個特定的問題。正如你可以看到錯誤計數被打印出來一樣,它被捕獲並且不包括在發生錯誤的函數內部的錯誤計數中,但被包含在包裝腳本中的函數之外。我想知道爲什麼這樣我可以弄清楚如何正確地忽略它。或者,如果可以使用更好的「變量」進行錯誤處理,我想知道那是什麼。 – Kemilio

回答

2

您的try-catch沒有捕獲錯誤(即使您沒有提供所有代碼)的主要問題是您的cmdlet顯式調用-ErrorAction SilentlyContinue。 Try/Catch塊要求使用終止錯誤,所以對於函數/ cmdlet,您需要更改爲-ErrorAction Stop,以便try/catch正確處理來自該函數/ cmdlet的錯誤。

這需要更新我們無法看到的代碼中的任何其他函數/ cmdlet。在下面的評論中描述

編輯:

$n = New-Object PSObject -property @{ 
    'Test1' = '' 
    'Test2' = '' 
    'Test3' = '' 
} 

try { 
    get-process someprocess -ErrorAction Stop 
    $n.Test1 = $true 
} catch { 
    $n.Test1 = $false 
} 

try { 
    Get-WmiObject win32_computersystem -ErrorAction Stop 
    $n.Test2 = $true 
} catch { 
    $n.Test2 = $false 
} 

try { 
    Get-Content somefile.ext -ErrorAction Stop 
    $n.Test3 = $true 
} catch { 
    $n.Test3 = $false 
} 


if ($n.Test1 -and $n.Test2 -and $n.Test3) { 
    ## All procedures completed successfully -- do something magical 
} else { 
    ## At least one test procedure failed. 
} 
+0

函數內部發現的錯誤在函數完成後仍然返回爲錯誤?看起來好像我的Extraction/Insertion_Function內部的錯誤被捕獲了,但是當這個函數完成並且我的包裝繼續執行時,錯誤會將堆棧作爲非終止錯誤備份起來。 – Kemilio

+0

聽起來好像你正在嘗試自己創建一個kludgy錯誤處理機制來確定代碼中不同部分的成功或失敗。如果我有一個依賴於其他一些進程成功的進程,我按照上面我編輯的方式處理它。嘗試/抓住你的特定片段,而不是計數$ error變量,明確測試它(見上文)。 – thepip3r

1

記錄剩餘的錯誤,因爲最後的日誌:

While ($Global:ErrorCount -lt $Error.Count) { 
    $Err = $Error[$Error.Count - ++$Global:ErrorCount] 
    $ErrLine = "Error at $($Err.InvocationInfo.ScriptLineNumber),$($Err.InvocationInfo.OffsetInLine): $Err" 
    Write-Host $ErrLine -ForegroundColor Red  # Log this 
} 
2

更換SilentlyContinueIgnore忽略錯誤,並沒有增加它的數量。

Extraction/Insertion_Function -serverList $serverList -insertionDB $insertionDB -ErrorAction Ignore 

抓住它裏面的功能,在thepip3r的答案try/catch語句唯一的缺點終止錯誤使用-ErrorAction Stop的。

+0

即使忽略包裝器腳本中的驅動程序功能,錯誤計數仍在函數之外增加。此外,我不希望整個驅動程序功能使用-EA忽略,因爲存在潛在的問題,我不想忽略。 – Kemilio