Żądanie sieci Web programu PowerShell bez zgłaszania wyjątku na 4xx / 5xx


82

Piszę skrypt PowerShell, który musi wykonać żądanie sieciowe i sprawdzić kod stanu odpowiedzi.

Próbowałem napisać to:

$client = new-object system.net.webclient

$response = $client.DownloadData($url)

tak dobrze jak to:

$response = Invoke-WebRequest $url

ale za każdym razem, gdy strona internetowa ma kod stanu, który nie jest kodem stanu sukcesu, PowerShell kontynuuje i zgłasza wyjątek zamiast podawać mi rzeczywisty obiekt odpowiedzi.

Jak mogę uzyskać kod statusu strony, nawet jeśli się nie ładuje?


To zadziałało dla mnie docs.microsoft.com/en-us/powershell/module/ ... Przykład 7: Przechwytywanie wiadomości o niepowodzeniu z Invoke-WebRequest
user3520245

Odpowiedzi:


121

Spróbuj tego:

try { $response = Invoke-WebRequest http://localhost/foo } catch {
      $_.Exception.Response.StatusCode.Value__}

To trochę kłopotliwe, że rzuca to wyjątek, ale tak właśnie jest.

Aktualizuj według komentarzy

Aby upewnić się, że takie błędy nadal zwracają prawidłową odpowiedź, możesz przechwycić te wyjątki typu WebExceptioni pobrać powiązane Response.

Ponieważ odpowiedź na wyjątek jest typu System.Net.HttpWebResponse, podczas gdy odpowiedź z pomyślnego Invoke-WebRequestwywołania jest typu Microsoft.PowerShell.Commands.HtmlWebResponseObject, aby zwrócić zgodny typ z obu scenariuszy, musimy pobrać pomyślną odpowiedź BaseResponse, która również jest typu System.Net.HttpWebResponse.

Kod stanu tego nowego typu odpowiedzi jest wyliczeniem typu [system.net.httpstatuscode], a nie prostą liczbą całkowitą, więc musisz bezpośrednio przekonwertować go na int lub uzyskać dostęp do jego Value__właściwości, jak opisano powyżej, aby uzyskać kod numeryczny.

#ensure we get a response even if an error's returned
$response = try { 
    (Invoke-WebRequest -Uri 'localhost/foo' -ErrorAction Stop).BaseResponse
} catch [System.Net.WebException] { 
    Write-Verbose "An exception was caught: $($_.Exception.Message)"
    $_.Exception.Response 
} 

#then convert the status code enum to int by doing this
$statusCodeInt = [int]$response.BaseResponse.StatusCode
#or this
$statusCodeInt = $response.BaseResponse.StatusCode.Value__

5
Dzięki, zadziałało. Nie zdawałem sobie sprawy, że możesz po prostu uzyskać dostęp do obiektu Response z obiektu Exception.
jcarpenter2

1
Tak, dotarcie do właściwego numeru kodu było trochę trudne. :-)
Keith Hill

Moje przejście do używa tego kodu od Chrisa Wahla, wahlnetwork.com/2015/02/19/…
FoxDeploy

11
Nieco lepszy sposób: $ response = try {Invoke-WebRequest localhost / foo } catch {$ _. Exception.Response} W ten sposób otrzymasz coś w zmiennej $ response w obu przypadkach. Należy jednak pamiętać, że niepowodzenie zwraca HtmlWebResponse, ale sukces zwraca HtmlWebResponseObject. W szczególności, StatusCode na tych jest różnych typów (westchnij)
Rob Cannon

4
Kilka drobnych poprawek do wielkiego sugestię Roba, aby uniknąć problemu z różnych typów: $response = try { (Invoke-WebRequest -Uri 'localhost/foo' -ErrorAction Stop).BaseRequest } catch [System.Net.WebException] { $_.Exception.Response }. BaseRequestTo znaczy, że pobieranie zapewnia, że ​​zarówno w scenariuszach sukcesu, jak i błędów otrzymujemy plik HttpWebReqponse. Dodanie [System.Net.WebException]zapewnia, że ​​w ten sposób wychwytujemy tylko istotne wyjątki / nie usuwamy przypadkowo innych typów problemów.
JohnLBevan

6

Od wersji Powershell 7.0 Invoke-WebRequestmają -SkipHttpErrorCheckparametr przełącznika.

-SkipHttpErrorCheck

Ten parametr powoduje, że polecenie cmdlet ignoruje stany błędów HTTP i kontynuuje przetwarzanie odpowiedzi. Odpowiedzi na błędy są zapisywane w potoku tak, jakby się powiodły.

Ten parametr został wprowadzony w programie PowerShell 7.

żądanie ściągnięcia dokumentów


0

-SkipHttpErrorCheck jest najlepszym rozwiązaniem dla PowerShell 7+, ale jeśli jeszcze nie możesz z niego korzystać, oto prosta alternatywa, która jest przydatna w przypadku interaktywnych sesji Poweshell z wiersza poleceń.

Gdy zobaczysz opis błędu dla odpowiedzi 404, tj.

Serwer zdalny zwrócił błąd: (404) nie znaleziono.

Następnie możesz zobaczyć `` ostatni błąd '' z wiersza poleceń, wpisując to:

$Error[0].Exception.Response.StatusCode

Lub

$Error[0].Exception.Response.StatusDescription

Lub cokolwiek innego, co chciałbyś wiedzieć o obiekcie `Response '.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.