如何在PowerShell中获取数字HTTP状态码

26
我知道用PowerShell构建Web客户端的几种好方法:.NET类System.Net.WebClient和System.Net.HttpWebRequest,或者COM对象Msxml2.XMLHTTP。据我所知,唯一一个可以访问数字状态码(例如200、404)的是最后一个COM对象。我的问题是我不喜欢它的工作方式,也不喜欢依赖于COM对象的存在。我还知道,微软会不时地决定杀死COM对象(ActiveX kill bits),因为存在安全漏洞等问题。
还有其他我不知道的.NET方法吗?这些其他两个对象中是否有状态码,而我只是不知道如何获取?
4个回答

69

结合x0n和Joshua Ewer的答案,为了完整地展示一个代码示例,希望这种方式不算太糟糕:

$url = 'http://google.com'
$req = [system.Net.WebRequest]::Create($url)

try {
    $res = $req.GetResponse()
} 
catch [System.Net.WebException] {
    $res = $_.Exception.Response
}

$res.StatusCode
#OK

[int]$res.StatusCode
#200

2
当它接收到除了2xx消息以外的任何内容时,会抛出异常(我认为)。在我看来,这不是预期的行为。 - Joe Phillips
1
@JoePhilllips 我在代码片段中添加了 try..catch,以便它可以处理其他状态码。 - merv
记得为 $req 设置一个 Timeout,否则它会无限期等待,这让我吃了亏! - Liam
个人而言,我更喜欢使用Invoke-WebRequest来简化它。-- Import-Csv .\SomePages.csv | Select-Object @{Name="URL";Expression={$.URL}}, @{Name="Status";Expression={ try{$res = (Invoke-WebRequest ("http://www.anonymized.com" + $.URL) -MaximumRedirection 0 -ErrorAction Ignore)} catch [System.Net.WebException] { $res = $_.Exception.Response}; $res.StatusCode}} | Export-Csv .\SomePagesStatus.csv - CodeMonkey1313
3
你还应该添加 $req.method = "HEAD",仅下载标头而不是整个响应,因为整个响应可能非常大。 - Chris
显示剩余2条评论

14
使用枚举类型 [system.net.httpstatuscode]
ps> [enum]::getnames([system.net.httpstatuscode])
Continue
SwitchingProtocols
OK
Created
Accepted
NonAuthoritativeInformation
NoContent
ResetContent
...

要获取数字代码,请将其强制转换为 [int]:

ps> [int][system.net.httpstatuscode]::ok
200

希望这能有所帮助,

-Oisin


啊哈,答案就在那里(我之前看到过OK字符串),但我不知道!太好了,谢谢。 :) - halr9000

5

我知道问题的标题是关于PowerShell的,但实际上并不是问题所要求的内容?无论如何...

WebClient是HttpWebRequest的一个非常简化的包装器。如果您只需要对服务进行非常简单的消费或发布一些Xml,那么WebClient非常适合您,但是它的缺点是它不够灵活。您将无法从WebClient获取所需的信息。

如果您需要状态代码,请从HttpWebResponse中获取。如果您正在执行类似于以下操作(仅向Url发布字符串):

var bytes = 
    System.Text.Encoding.ASCII.GetBytes("my xml"); 

var response = 
    new WebClient().UploadData("http://webservice.com", "POST", bytes);

如果你想获取状态码,可以使用HttpWebRequest。这个方法的思路是一样的,只不过有更多的选项(因此需要更多的代码)。

//create a stream from whatever you want to post here
var bytes = 
  System.Text.Encoding.ASCII.GetBytes("my xml"); 
var request = 
  (HttpWebRequest)WebRequest.Create("http://webservice.com");

//set up your request options here (method, mime-type, length)

//write something to the request stream
var requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);        
requestStream.Close();

var response = (HttpWebResponse)request.GetResponse();

//returns back the HttpStatusCode enumeration
var httpStatusCode = response.StatusCode;

哦,resposne.statuscode是字符串,然后我使用x0n的枚举器技术将其转换为数字。谢谢 :) - halr9000
如果我在标题中省略了PowerShell,那么我得到的答案肯定会更远离我想要的结果。但我肯定能读懂你的代码。 - halr9000

0

看起来非常简单

$wc = New-Object NET.WebClient
$wc.DownloadString($url)
$wc.ResponseHeaders.Item("status")

您可以在ResponseHeaders属性中找到其他可用的响应头(例如content-type、content-length、x-powered-by等),并通过Item()方法检索其中任何一个。

但正如下面Rob所提到的,遗憾的是,在这里状态属性不可用。


3
这是每个人都想要的工作方式,但事实并非如此。使用NET、WebClient进行请求后,在响应头中没有“状态”信息。更糟糕的是,如果响应状态不是200,则会引发异常并且响应头属性为空。 - rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接