前天有群友问:如何获取文本文件中的网址的状态码,我以为用Get-Content和Invoke-WebRequest就够了,没想到,Invoke-WebRequest还有它矫情的一面,比如当遇到德高望重的方校长时,它不会返回404,而是直接报错,即使指定ErrorAction,也无济于事。
PS C:\> Invoke-WebRequest https://www.pstips.net/love -ErrorAction SilentlyContinue
Invoke-WebRequest : 远程服务器返回错误: (404) 未找到。
所在位置 行:1 字符: 1
+ Invoke-WebRequest https://www.pstips.net/love -ErrorAction SilentlyContinue
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest],WebExce
ption
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
这很让人怀疑,这是不是Invoke-WebRequest的一个bug,事实上不是,而是by design,因为在.NET中,WebRequest和HttpWebRequest的表现都是一样。并且,Invoke-WebRequest并没有给任何人承诺过,它可以返回所有请求的状态码。只是我们可能自作多情了。既然Invoke-WebRequest,关上了这一扇门,那它打开的另一扇窗户是什么?就是上面抛出的异常:System.Net.WebException
所以我们只需要捕获异常中的WebException,针对它的属性Response.StatusCode进行处理即可。
在使用Invoke-WebRequest时,可以指定Method为HEAD,这样就只返回Header部分信息,不返回body,可以提高效率。
根据我的测试,当服务器返回状态码为100时,没有Response,所以单独处理。
Function Detect-HttpStatusCode ([uri]$Url)
trap [Net.WebException]
if($_.Exception.Response -eq $null)
return 100
return [int]($_.Exception.Response.StatusCode)
return (Invoke-WebRequest $Url ).StatusCode
既然是私人定制版,要测就测个全套的,将所有HTTP状态码全部测一遍。下面是我的步骤:
我自己新建了一个ASP.NET MVC工程。添加了一个控制器HTTP,里面放了一个Action叫Test,具体是这样写的:
public class HTTPController : Controller
// GET: /HTTP/
public ActionResult Index()
return View();
public ActionResult Test(int id)
Response.StatusCode = id;
Response.End();
return View();
如果对此无异议,我把该网站部署在本地42833端口,使用下面脚本测试:
[Enum]::GetNames([Net.httpStatusCode]) | foreach {
$expectedCode = [int][net.httpstatuscode]$_
$actualCode = Detect-HttpStatusCode -Url "http://localhost:42833/http/test/$expectedCode"
Write-Host "$($_) -> $actualCode `t" -NoNewline
if($expectedCode -eq $actualCode)
Write-Host '[Passed]' -ForegroundColor Green
Write-Host "[Failed]" -ForegroundColor Red
下面的输出,就用一张图来说明吧!
检查网址的HTTP状态码