Posting HTTP form without using 'Invoke-WebRequest'
Solution 1
Here is the code I use to post my Web requests, this is not the exact answer, but I suppose you can adapt it :
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
}
}
Solution 2
It looks like I was very close to getting it working. For some reason, I also needed to include __VIEWSTATE (in addition to __EVENTVALIDATION) in the POST. I was able to determine this by verifying form data via 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();
MKANET
Updated on August 10, 2022Comments
-
MKANET over 1 year
I have a working PowerShell 3.0 script that takes advantage of
Invoke-WebRequest
to post a form and save the respective raw HTML output. Unfortunately, the script doesn't work on workstations with only PowerShell 2.0.I was hoping someone could please help convert the below script to work with PowerShell 2.0 (without having to install PS modules, packages, or upgrade PowerShell). It looks like I need to use .NET webclient, but I'm not experienced enough to do this yet. A working example (based on my script) would be extremely appreciated!
PS: I'm using
sls -pattern
to filter out content in the raw HTML output. If there's a more reliable way to identify certain items in the raw output, I wouldn't mind seeing an example.$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
EDIT: Below, is my first attempt at getting the script to work. Anyway, it's obviously not doing the same thing as my WORKING Invoke-WebRequest script above
$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();