HTTP Status codes via Powershell - powershell

Somehow the below codes works fine for the first few test URLs within C:\testurl.txt then it hung up forever when it is processing the 4th URL from the C:\testurl.txt , no idea why it hangs up?
It is already working fine for up to 3 URLs but stuck up on 4th onward
CLS
$urllist = Get-Content "C:\testurl.txt" # URLs to test one in each line
foreach ($url in $urllist) {
Write-Host $url
$req = [System.Net.WebRequest]::Create($url)
try {
$res = $req.GetResponse()
} catch [System.Net.WebException] {
$res = $_.Exception.Response
}
$res.StatusCode
#Print OK or whatever
[int]$res.StatusCode
#Print 200 or whatever
}
It is working fine for up to 3 URLs but hangs the script on 4th URL without any output or error message. Here is the example of c:\testurl.txt
http://www.google.com
http://www.google.com
http://www.google.com
http://www.google.com
http://www.hotmail.com
http://www.gmail.com
http://www.yahoo.com
http://www.msn.com
Please note each URL will be in a new line, you will see that script will stop at (the 4th one) you may try with your own URLs, etc too

then it hung up forever
No - it's hung until the underlying TCP connections of the previous requests time out.
The .NET CLR will internally pool all WebRequest dispatches so that only a finite number of external requests will be initiated concurrently, and as long as you have a number of un-closed WebResponse objects in memory, your requests will start queuing up.
You can avoid this by closing them (as you should):
foreach ($url in $urllist) {
Write-Host $url
$req = [System.Net.WebRequest]::Create($url)
try {
$res = $req.GetResponse()
}
catch [System.Net.WebException] {
$res = $_.Exception.Response
}
finally {
$res.StatusCode
#Print OK or whatever
[int]$res.StatusCode
#Print 200 or whatever
$res.Dispose()
# close connection, dispose of response stream
}
}

Related

Need help to grab only most recent entry of a specific instance from a troubleshooting log

I wrote a PowerShell script which uses APIs to parse through non-compliant (NC) mobile device logs from our MDM to determine if a device has been NC for over 60 days and delete it. We realized that current compliant devices that become NC might have an older record from a previous time they were NC. We only want to grab the latest log entry. Any help to understand how to only grab the most recent NC entry would be great.
Have not been able to write code that would only grab the latest non-compliant entry from the logs. Currently it will grab all NC log entries ≥ 60 days from each device that is NC. In the function I return the serial number of the device if it has been NC for over 60 days.
The code below is the function that I wrote to parse the event logs and does work, minus the fact that it grabs any older NC log entry ≥60 days. I'm assuming I could put some code in the foreach statement.
function get_events {
Param([string]$serial)
$sixtydays = (Get-Date).AddDays(-60)
$url = "https://$ourmdm/api/mdm/devices/eventlog?searchby=serialnumber&id=$serial&pagesize=10000&dayrange=365"
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("tenant-code", $Code)
$headers.Add("Authorization", $Auth)
try {
$response = Invoke-RestMethod -Uri $url -Headers $headers
} catch {
$null = "Device Info Not Found"
}
$ServicePoint = [System.Net.ServicePointManager]::FindServicePoint($url)
$ServicePoint.CloseConnectionGroup("") | Out-Null
$data = $response.DeviceEventLogSearchResult.DeviceEventLogEntries
foreach ($event in $data) {
if ($event.Event -eq 'ComplianceStatusChanged') {
if ($event.EventDataList.NewValue -eq 'NonCompliant') {
$request = $event.Timestamp
$eventdate = [DateTime]$request
if ($eventdate -lt $sixtydays) {
return $serial
}
}
}
}
}

How to run a web request using default credentials in Powershell

I am working on the following code.
$HTTP_Request =[System.Net.WebRequest]::Create('http://google.com')
$HTTP_Response = $HTTP_Request.GetResponse()
$HTTP_Status = [int]$HTTP_Response.StatusCode
echo $HTTP_Status
But I want to run it using my default credentials, because there are few URLs which returns 401 ,that is client not authorized and for that I need it to run using my default credentials.
Can anyone help me regarding same, as I want to store the status of some URLs and this code is working fine except for those which are protected.
So the question was to run web request while using default credentials, here are the solutions I found:
for powershell 2.0:-
$req = [system.Net.WebRequest]::Create($uri)
$req.UseDefaultCredentials = $true
try
{
$res = $req.GetResponse()
}
catch [System.Net.WebException]
{
$res = $_.Exception.Response
}
$int = [int]$res.StatusCode
echo $int
For Powershell 3.0:-
try{
$res = Invoke-WebRequest $uri -UseDefaultCredentials
}
catch [System.Net.WebException]
{
$res = $_.Exception.Response
}
$int = [int]$res.StatusCode
echo $int
Both scripts are extremely doing well but if you want to find code status of many URLs, then you should go for powershell 3.0 , it handles web-requests in a much better way.

Restart application pool based on http response code

I am trying to write a PowerShell script that will restart an application pool in IIS if a 503 response code is received.
So far I have managed to retrieve the response code for every crm application under the default website in IIS. However I am unsure how I would go about finding the application pool name. I've tried the below, but it returns the same application pool for each site. Can anyone help?
$getSite = (Get-WebApplication -Site 'Default Web Site')
$SiteURL = ForEach ($site in $getSite.path) {("http://localhost")+$site}
ForEach ($crm in $SiteURL){
$req = [system.Net.WebRequest]::Create($crm)
try {
$res = $req.GetResponse()
} catch [System.Net.WebException] {
$res = $_.Exception.Response
}
$ApplicationPool = ForEach ($app in $getSite.applicationpool) {$app}
if([int]$res.StatusCode -eq 503) {write-host ($crm + ' ' + [int]$res.StatusCode) + $app}
}
I think you need to access $_.Exception.InnerException for the the Response property.
Your $ApplicationPool assignment doesn't make much sense, as you would only need one applicationPool name per $crm app you test:
foreach($App in #(Get-WebApplication -Site 'Default Web Site')){
# Uri for the application
$TestUri = 'http://localhost{0}' -f $App.path
# Create WebRequest
$Request = [system.Net.WebRequest]::Create($TestUri)
try {
# Get the response
$Response = $Request.GetResponse()
} catch [System.Net.WebException] {
# If it fails, get Response from the Exception
$Response = $_.Exception.InnerException.Response
}
# The numerical value of the StatusCode value is the HTTP status code, ie. 503
if(503 -eq ($Response.StatusCode -as [int])){
# Restart the app pool
Restart-WebAppPool -Name $App.applicationPool
}
}

Get HTTP request and tolerate 500 server error in powershell

In Powershell v3.0 I would like to return the response code from an HTTP GET, such as 200 OK or 500 Internal Server Error. (This is for a hack-deploy to do a quick warmup of a deployed site and see if it works, a sort of a mini acceptance test. The status code is truly all I want.)
Against my wishes, HttpWebRequest.GetResponse throws an error when it receives a 500 Internal Server Error. This is annoying because it isn't really an error to me in my use case. Anyway, I figured I could catch the exception and still peel out the underlying response code, but I'm having trouble with that.
Here's some almost-working code:
function WebResponseStatusCode (
[Parameter(Mandatory=$true)][string] $url
) {
$req = [system.Net.HttpWebRequest]::Create($url)
try {
$res = $req.GetResponse();
$statuscode = $res.statuscode;
}
catch [System.Net.WebException] {
#the outer error is a System.Management.Automation.ErrorRecord
Write-Host "error!"
return = $_.Response.statuscode; #nope
}
finally {
if (!($res -eq $null)) {
$res.Close();
}
}
return $statuscode;
}
The problem is of course that $_ has no Response property. Neither does $_.InnerException, even when cast:
return [System.Net.WebException]($_.InnerException)
I've played around with $_ | Get-Member and exploring all its properties. I thought $_.TargetObject had some promise but it doesn't appear to.
(Update) I also think I tried variations on $_.Exception.Response though may have gotten it wrong.
Getting just a response code seems like such a simple thing to do.
Here's an example, though it does a couple more things to allow you to test redirections as well as expected exceptions.
function GetWebSiteStatusCode {
param (
[string] $testUri,
$maximumRedirection = 5
)
$request = $null
try {
$request = Invoke-WebRequest -Uri $testUri -MaximumRedirection $maximumRedirection -ErrorAction SilentlyContinue
}
catch [System.Net.WebException] {
$request = $_.Exception.Response
}
catch {
Write-Error $_.Exception
return $null
}
$request.StatusCode
}
GetWebSiteStatusCode -testUri "https://www.google.com/"
GetWebSiteStatusCode -testUri "https://www.google.com/foobar"
GetWebSiteStatusCode -testUri "http://google.com/" -maximumRedirection 0
GetWebSiteStatusCode -testUri "https://accounts.google.com" -maximumRedirection 0
GetWebSiteStatusCode -testUri "https://www.googleapis.com/coordinate/v1/teams/1/custom_fields?fields=1111&key="
GetWebSiteStatusCode -testUri "https://www.googleapis.com/shopping/search/v1/test/products/sasdf/asdf/asdf?key="
#Next test would be for an expected 500 page.
#GetWebSiteStatusCode -testUri "https://www.somesite.com/someurlthatreturns500"

Powershell Command: HttpWebRequest stucks after fetching two requests

I have a list of URL in a text file and I want to test whether all of them are reachable or not. I fired the following command in windows powershell but somehow after displaying the status of first two requests, the command stucks somewhere and never returns. Am I missing something?
cat .\Test.txt | % { [system.Net.WebRequest]::Create("$_").GetResponse().StatusCode }
Text File
http://www.google.com
http://www.yahoo.com
http://www.bing.com
Output:
OK
OK
----> after that it stucks.
use Invoke-WebRequest instead:
$sites = 'http://www.google.com','http://www.yahoo.com','http://www.bing.com'
foreach ($site in $sites) {
Invoke-WebRequest $site
$site
}
From memory: You have to explicitly close the Response stream:
$req = [System.Net.HttpWebRequest]::Create($aRequestUrl);
$response = $null
try
{
$response = $req.GetResponse()
# do something with the response
}
finally
{
# Clear the response, otherwise the next HttpWebRequest may fail... (don't know why)
if ($response -ne $null) { $response.Close() }
}