2012-07-11 13 views
7

Występuje specyficzny problem z Powershell. Przechwytywam wyjątek w bloku catch, ale globalny obiekt błędu $ nie jest wypełniany.

trywialny przykład, gdzie byłoby to zachowują się zgodnie z oczekiwaniami to:

function Bar 
{ 
    Foo 
} 

function Foo 
{ 
    try 
    { 
    $Error.Clear() 
    throw "Error!" 
    } 
    catch 
    { 
    "Caught an error - current error count $($Error.Count)" 
    } 
    finally 
    { 
    "Cleaning up - current error count $($Error.Count)" 
    } 
} 

wyjściowy jest jak można się spodziewać, jeśli dzwonisz Bar

Caught an error - current error count 1 
Cleaning up - current error count 1 

Kodeksu mam problemy z jest prawie identyczne, z wyjątkiem tego, że ładuje Foo z modułu. Nie wiem, czy jest to błąd, czy po prostu coś, czego nie rozumiem (będzie musiał sprawdzić mój PowerShell w książce działania!)

Gdybym zapisać Foo się do modułu - Foo.psm1

function Foo 
{ 
    try 
    { 
    $Error.Clear() 
    throw "Error!" 
    } 
    catch 
    { 
    "Caught an error - current error count $($Error.Count)" 
    } 
    finally 
    { 
    "Cleaning up - current error count $($Error.Count)" 
    } 
} 

Export-ModuleMember -Function Foo 

Potem należy wykonać następujące

Import-Module .\Foo.psm1 
$Error.Clear() 
"Current error count $($Error.Count)" 
Foo 
"Current error count $($Error.Count)" 

I skończyć z

Current error count 0 
Caught an error - current error count 0 
Cleaning up - current error count 0 
Current error count 1 

Zauważ, że Foo nie widzi Niu zmiany wprowadzone do $ Błąd. Tak więc moduł-ification kodu zmienia zachowanie propagacji błędu. Czy ktokolwiek może wtrącić się za tym rozumowaniem?

Powinienem zauważyć, że mogę uzyskać określony wyjątek odłowu za pomocą zmiennej automatycznej $ _, ale szukam, aby uzyskać cały zbiór w tym momencie stosu wywołań.

+0

Więc moja pierwsza linia powyżej jest nie tak .. globalny zbiór $ Błąd został zmodyfikowany, ale moduł scoped kolekcja $ Błąd nie jest. –

Odpowiedz

7

Nie zauważyłem tego wcześniej, ale być może kolekcja błędów $ ma zasięg do modułu jak wszystkie inne zmienne. Spróbuj porównując wartości następujących dwóch wyraźnie scoped zmiennych w kluczowych punktach w skrypcie testowym:

"Errors - Global: {0}; Module: {1}" -f $global:error.count, $script:error.count 

Daj mi znać, jak można dostać się na.

+0

Możliwe, że $ error.clear() kopiuje zmienną globalną do zakresu lokalnego i czyści to. –

+0

Jednym ze sposobów uzyskania zmiennej Błąd w zakresie modułu byłaby "Zmienna Get -Name Error -Scope 2". @Etan, ponieważ masz PS w akcji, możesz zajrzeć do sekcji '9.4.5. Jak działają skoki w modułach skryptów ?. –

+0

Teraz czuję się trochę głupio ... Nie mogę w tej chwili sprawdzić, ale podejrzewam, że problem dotyczy tutaj zakresu. Całkowicie poślizgnął się mój umysł (co jest gorsze, ponieważ mam kilka $ script: level vars w kodzie)! Sprawdzę ponownie 9.4.5 - dzięki Andy!Sądzę, że szczególną cechą byłoby to, że dostęp do błędu $ w module nie ma rozsądnego domyślnego zakresu - w końcu wyjątek pojawił się w module, więc można by pomyśleć, że błąd $ byłby domyślny dla tablicy, w której zbierane były błędy modułów . –

9

Jak wspomniał Ethan, należy spojrzeć na $ global: błąd, aby zobaczyć wszystkie błędy. Moduły zawsze mają własną zmienną błędu $, ale jest ona (w większości przypadków) nieużywana.

tło: w pewnym momencie rozważaliśmy izolowanie błędów, które wystąpiły w kodzie modułu, do zakresu modułów, ale ostatecznie zdecydowaliśmy się dodać wszystkie błędy do globalnego zbioru błędów, ponieważ jest to w zasadzie dziennik błędów (jak w pamięci). eventlog.) Niestety błąd związany z błędem modułu $ nie został usunięty przed wydaniem, więc musisz użyć globalnego kwalifikatora zasięgu, aby uzyskać dostęp do "prawdziwej" zmiennej błędu $.

Bruce Payette, Microsoft Corporation

+0

Bruce - dzięki za historyczne tło. To jest dokładnie ten typ informacji, którego szukałem. –

Powiązane problemy