2017-06-08 4 views
1

Ich arbeite mit einem Wrapper-Skript, das eine Funktion aufruft, die einige Datenbanken innerhalb angegebener Server abfragt und Metadaten in eine bestimmte Datenbank auf einem separaten Server einfügt. Ich verwende die Variable $ error.count, um festzustellen, ob das Skript erfolgreich war oder nicht. Ich erwarte einige Erlaubnis-/Extraktionsfehler und möchte, dass diese gefangen und ignoriert werden (keine Zunahme in der Variablen $ error.count, aber eine Warnung, die in das Jobprotokoll geschrieben wird). Ich kann bestätigen, dass ein Berechtigungsfehler vorliegt und ordnungsgemäß abgefangen wird. Die Variable $ error.count wird nicht erhöht, aber es wird eine Warnung aus dem Catch ausgegeben, die die Datenbank anzeigt, auf die nicht zugegriffen werden konnte.Abfangen von Kaskadierungsfehlern in PowerShell

Mein Problem tritt auf, nachdem die Extraktions-/Einfügefunktion beendet wurde. Unmittelbar nachdem diese Funktion zum Wrapper-Skript zurückkehrt, lasse ich die Variable $ error.count erneut drucken. Diesmal gibt es eine 1 zurück, als ob der vorher gefangene Fehler in das Wrapper-Skript überging. Wie ich bereits erwähnt habe, möchte ich nicht, dass dies in der Fehlerzählung enthalten ist. Ich bin nicht sicher, wie oder warum der $ error.count von dieser Funktion erhöht wird.

Sollte ich eine andere Variable verwenden, um festzustellen, ob das Skript "fehlgeschlagen" ist oder nicht? Gibt es einen Grund dafür, dass $ error.count außerhalb der Funktion, die den Fehler hat, erhöht wird, während sie nach dem Fehler nicht erhöht wird? Jede Anleitung zu diesem Thema wäre willkommen.

-Code als Referenz: Wrapper-Funktion:

$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: $_" 
    } 

Extraction/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" 
       } 
} 

ich dann die Fehleranzahl innerhalb der Schleife Druck aus, die extrahiert/fügt die Metadaten aus jeder Datenbank in die Einfügedatenbank sowie in die Schleife für jeden Server, der die Datenbanken enthält:

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** 

Der Fehler (Berechtigungsproblem) wird innerhalb der Funktion abgefangen, kaskadiert aber auf mein Wrapper-Skript. Ich möchte, dass dieser spezielle Fehler ignoriert wird, während andere, schwerwiegendere Fehler NICHT ignoriert werden (z. B. keine Verbindung zu dem Server herstellen zu können, in den ich die Metadaten einfüge), so dass -EA Ignore auf der Treiberfunktion innerhalb des Wrapper-Skripts liegt Frage.

+0

Hier ist nicht genügend Code vorhanden, um zu bestimmen, was Sie tun. Bitte geben Sie eine [MCVE] an. Eine Sache, die Sie wissen sollten, '$ error.Count' ist keine Variable. '$ error' ist eine (spezielle) Variable, und es ist ein Array, das alle Fehler enthält, also zeigt' $ error.Count' die Größe des Arrays an. '$ error' hängt an den Anfang, nicht an das Ende, also ist' $ error [0] 'immer der letzte Fehler. Wenn Sie wissen wollen, warum der Zählerstand steigt, schauen Sie sich vor und nach dem Aufruf '$ error [0]' an, da Ihnen der tatsächliche Fehler einen Hinweis gibt, was passiert. – briantist

+0

Ich weiß was los ist. Es ist ein Berechtigungsproblem. Mein Problem ist, dass ich dieses spezielle Problem ignorieren möchte. Wie Sie anhand der ausgedruckten Fehleranzahl erkennen können, wird sie abgefangen und ist nicht in der Fehlerzählung innerhalb der Funktion enthalten, in der der Fehler auftritt, sondern außerhalb der Funktion im Wrapper-Skript. Ich möchte wissen, warum das so ist, damit ich herausfinden kann, wie ich es richtig ignorieren kann. Oder, wenn eine bessere "Variable" für die Fehlerbehandlung verwendet werden könnte, würde ich gerne wissen, was das ist. – Kemilio

Antwort

2

Ihr primäres Problem mit dem try-catch, das den Fehler nicht abfängt (obwohl Sie nicht den gesamten Code bereitstellen), ist, dass Ihr Cmdlet explizit -ErrorAction SilentlyContinue aufruft. Versuchen/Catch-Blöcke erfordern die Verwendung von Terminierungsfehlern, so dass im Falle Ihrer Funktion/Cmdlet, müssen Sie für Try/Catch zu -ErrorAction Stop ändern, um einen Fehler von dieser Funktion/Cmdlet entsprechend umzugehen.

Dies muss für jede andere Funktion/Cmdlet im Code aktualisiert werden, die wir nicht sehen können.

bearbeiten unten in den Kommentaren beschrieben:

$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

Fangen gefangene Fehler innerhalb von Funktionen immer noch als Fehler zurück, nachdem die Funktion beendet ist? Es scheint, als ob der Fehler innerhalb meiner Extraction/Insertion_Function abgefangen wird, aber wenn diese Funktion beendet ist und mein Wrapper seine Ausführung fortsetzt, sichert der Fehler den Stack als nicht-terminierenden Fehler. – Kemilio

+0

Es klingt, als ob Sie selbst versuchen, einen Fehlerbehebungsmechanismus von kludgy zu erstellen, um den Erfolg oder das Fehlschlagen verschiedener Teile Ihres Codes festzustellen. Wenn ich einen Prozess habe, der darauf angewiesen ist, dass einige andere Prozesse erfolgreich sind, handle ich auf eine Weise, die in meiner obigen Bearbeitung angegeben ist. Probieren Sie/Fangen Sie Ihr spezifisches Segment und testen Sie die Variable $ error nicht explizit, sondern testen Sie explizit danach (siehe oben). – thepip3r

1

die verbleibenden Fehler seit dem letzten Log-Logging:

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

ersetzen SilentlyContinue mit Ignore den Fehler zu ignorieren und sie nicht die Zählung erhöhen haben.

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

es innerhalb der Funktion zu fangen, benutzen Sie -ErrorAction Stop wie in der Antwort des thepip3r als try/catch-Anweisungen nur Fehler fangen endet.

+0

Auch bei Ignorieren der Treiberfunktion im Wrapper-Skript wird die Fehleranzahl außerhalb der Funktion noch erhöht. Außerdem möchte ich nicht, dass die gesamte Treiberfunktion -EA Ignore verwendet, weil es potentielle Probleme gibt, die ich nicht ignorieren möchte. – Kemilio