【问题标题】:Posting HTTP form without using 'Invoke-WebRequest'在不使用“Invoke-WebRequest”的情况下发布 HTTP 表单
【发布时间】:2015-06-18 16:54:06
【问题描述】:

我有一个有效的 PowerShell 3.0 脚本,它利用 Invoke-WebRequest 发布表单并保存相应的原始 HTML 输出。不幸的是,该脚本不适用于只有 PowerShell 2.0 的工作站。

我希望有人可以帮助转换以下脚本以使用 PowerShell 2.0(无需安装 PS 模块、软件包或升级 PowerShell)。看起来我需要使用 .NET webclient,但我还没有足够的经验来做到这一点。非常感谢一个工作示例(基于我的脚本)!

PS:我正在使用sls -pattern 过滤掉原始 HTML 输出中的内容。如果有更可靠的方法来识别原始输出中的某些项目,我不介意看一个例子。

$UserAgent = 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET CLR 1.1.4322; InfoPath.3; MS-RTC LM 8; .NET4.0E)'
$r=Invoke-WebRequest -Uri 'http://web.ourwebserver.com/test.aspx' -UseDefaultCredentials -SessionVariable WebSession
$form = $r.Forms[0]

$fields = Invoke-WebRequest -Uri 'http://web.ourwebserver.com/test.aspx' -WebSession $WebSession | select -ExpandProperty inputfields | select name, value

$viewstate = $fields | ?{$_.name -match "VIEWSTATE"} | select -ExpandProperty value
$eventvalidation = $fields | ?{$_.name -match "EVENTVALIDATION"} | select -ExpandProperty value

$form.Fields["__EVENTVALIDATION"] = $eventvalidation
$form.Fields["ctl00`$MainContent`$phone"] = "454-454-2345"
$form.Fields["ctl00`$MainContent`$Submit"] = "Submit"

$response = Invoke-WebRequest -Uri 'http://web.ourwebserver.com/test.aspx' -WebSession $WebSession -Method POST -Body $form.Fields -ContentType 'application/x-www-form-urlencoded'
$result = $response.rawcontent

编辑:下面是我第一次尝试让脚本工作。无论如何,它显然与我上面的 WORKING Invoke-WebRequest 脚本不一样

$URL = "http://web.ourwebserver.com/test.aspx"
$wc = new-object net.WebClient
$wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded")
$wc.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET CLR 1.1.4322; InfoPath.3; MS-RTC LM 8; .NET4.0E)")
$wc.UseDefaultCredentials = $true

### EventValidation/ViewState Extraction Code ###
$probe = $wc.downloadData($url)
$s = [text.encoding]::ascii.getString($probe)
$start = $s.indexOf('id="__VIEWSTATE"', 0) + 24
$end = $s.indexOf('"', $start)
$viewstate = $s.substring($start, $end-$start)
$start = $s.indexOf('id="__EVENTVALIDATION"', 0) + 30
$end = $s.indexOf('"', $start)
$eventvalidation = $s.substring($start, $end-$start)
###

$NVC = New-Object System.Collections.Specialized.NameValueCollection
$NVC.Add("__EVENTVALIDATION", $eventvalidation)
$NVC.Add("ctl00`$MainContent`$phone", "454-454-2345")
$NVC.Add("ctl00`$MainContent`$Submit", "Submit")
$wc.QueryString = $NVC

$Result = $WC.UploadValues($URL,"POST", $NVC)

[System.Text.Encoding]::UTF8.GetString($Result)

$WC.Dispose();

【问题讨论】:

  • 我很确定我正确地发布了大部分答案。我认为在向 $NVC 添加值/数据时可能做错了。

标签: forms powershell powershell-2.0 webclient


【解决方案1】:

这是我用来发布我的网络请求的代码,这不是确切的答案,但我想你可以调整它:

Add-Type -AssemblyName System.ServiceModel.Web, System.Runtime.Serialization, System.Web.Extensions

$utf8 = [System.Text.Encoding]::UTF8

function Request-Rest
{
  [CmdletBinding()]
  PARAM (
         [Parameter(Mandatory=$true)]
         [String] $URL,

         [Parameter(Mandatory=$false)]
         [System.Net.NetworkCredential] $credentials,

         [Parameter(Mandatory=$true)]
         [String] $JSON)

  # Remove NewLine from json
  $JSON = $JSON -replace "$([Environment]::NewLine) *",""  

  # Create a URL instance since the HttpWebRequest.Create Method will escape the URL by default.   
  # $URL = Fix-Url $Url
  $URI = New-Object System.Uri($URL,$true)   

  try
  {
    # Create a request object using the URI   
    $request = [System.Net.HttpWebRequest]::Create($URI)   
    # Build up a nice User Agent   
    $UserAgent = "Your user agent name"
    $request.UserAgent = $("{0} (PowerShell {1}; .NET CLR {2}; {3})" -f $UserAgent, $(if($Host.Version){$Host.Version}else{"1.0"}),  
                           [Environment]::Version,  
                           [Environment]::OSVersion.ToString().Replace("Microsoft Windows ", "Win"))

    $request.Credentials = $credentials
    $request.KeepAlive = $true
    $request.Pipelined = $true
    $request.AllowAutoRedirect = $false
    $request.Method = "POST"
    $request.ContentType = "application/json"
    $request.Accept = "application/json"

    $utf8Bytes = [System.Text.Encoding]::UTF8.GetBytes($JSON)
    $request.ContentLength = $utf8Bytes.Length
    $postStream = $request.GetRequestStream()
    $postStream.Write($utf8Bytes, 0, $utf8Bytes.Length)
    #Write-String -stream $postStream -string $JSON
    $postStream.Dispose()

    try
    {
      #[System.Net.HttpWebResponse] $response = [System.Net.HttpWebResponse] $request.GetResponse()
      $response = $request.GetResponse()
    }
    catch
    {
      $response = $Error[0].Exception.InnerException.Response; 
      Throw "Exception occurred in $($MyInvocation.MyCommand): `n$($_.Exception.Message)"
    }

    $reader = [IO.StreamReader] $response.GetResponseStream()  
    $output = $reader.ReadToEnd()  

    $reader.Close()  
    $response.Close()
    Write-Output $output  
  }
  catch
  {
    $output = @"
    {
      "error":1,
      "error_desc":"Request-Rest Internal : Serveur access problem $($_.Exception.Message)"
    }
"@    
    Write-Output $output
  }
}

【讨论】:

    【解决方案2】:

    看起来我已经非常接近让它工作了。出于某种原因,我还需要在 POST 中包含 __VIEWSTATE(除了 __EVENTVALIDATION)。我能够通过 Fiddler 验证表单数据来确定这一点。

    $URL = "http://web.ourwebserver.com/test.aspx"
    $wc = new-object net.WebClient
    $wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded")
    $wc.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727)")
    $wc.UseDefaultCredentials = $true
    
    ### EventValidation/ViewState Extraction Code ###
    $probe = $wc.downloadData($url)
    $s = [text.encoding]::ascii.getString($probe)
    $start = $s.indexOf('id="__VIEWSTATE"', 0) + 24
    $end = $s.indexOf('"', $start)
    $viewstate = $s.substring($start, $end-$start)
    $start = $s.indexOf('id="__EVENTVALIDATION"', 0) + 30
    $end = $s.indexOf('"', $start)
    $eventvalidation = $s.substring($start, $end-$start)
    ###
    
    $NVC = New-Object System.Collections.Specialized.NameValueCollection
    $NVC.Add("__VIEWSTATE", $viewstate);
    $NVC.Add("__EVENTVALIDATION", $eventvalidation);
    $NVC.Add("ctl00`$MainContent`$phone", "454-454-2345");
    $NVC.Add("ctl00`$MainContent`$Submit", "Submit");
    $wc.QueryString = $NVC
    
    $Result = $WC.UploadValues($URL,"POST", $NVC)
    
    [System.Text.Encoding]::UTF8.GetString($Result)
    
    $WC.Dispose();
    

    【讨论】:

      【解决方案3】:

      如果您仍然需要可重用的脚本,那么您可以利用我为完全相同的问题编写的内容。我只需要使用 PowerShell 2.0 发布。该脚本在 GitHub 上的 nice Reusable Function 中可用:Request POST REST via Reusable Function

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-19
        • 2014-08-17
        • 2016-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多