2015-06-18 15 views
7

Mam działający skrypt PowerShell 3.0, który korzysta z Invoke-WebRequest, aby opublikować formularz i zapisać odpowiednie wyjściowe dane HTML. Niestety, skrypt nie działa na stacjach roboczych z tylko PowerShell 2.0.Wysyłanie formularza HTTP bez użycia 'Invoke-WebRequest'

Miałem nadzieję, że ktoś mógłby pomóc w konwersji poniższego skryptu do pracy z PowerShell 2.0 (bez konieczności instalowania modułów PS, pakietów lub aktualizacji PowerShell). Wygląda na to, że potrzebuję używać klienta WWW .NET, ale nie mam na tyle doświadczenia, aby to zrobić. Przykład pracy (oparty na moim scenariuszu) byłby niezwykle doceniony!

PS: Używam sls -pattern do odfiltrowywania zawartości surowego wyjścia HTML. Jeśli istnieje bardziej niezawodny sposób identyfikowania pewnych elementów w surowych wydrukach, nie miałbym nic przeciwko zobaczeniu przykładu.

$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: Poniżej jest moja pierwsza próba uzyskania skrypt do pracy. W każdym razie, to oczywiście nie robi to samo, co mój skrypt PRACY Invoke-WebRequest powyżej

$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(); 
+0

Jestem prawie pewny, że poprawnie wysłałem większość odpowiedzi. Myślę, że może robić coś nie tak podczas dodawania wartości/danych do $ NVC. – MKANET

Odpowiedz

0

Proste POST można zrobić w ten sposób. Proszę spróbuj, jeśli to działa.

$URL="http://yourweb.com" 

$NVC = New-Object System.Collections.Specialized.NameValueCollection 
$NVC.Add($NAME1, $NAME_VALUE); 
$NVC.Add($NAME2, $NAME_VALUE2); 
.. 

$WC = New-Object System.Net.WebClient 
$WC.UseDefaultCredentials = $true 
$Result = $WC.UploadValues($URL,"post", $NVC); 

[System.Text.Encoding]::UTF8.GetString($Result) 
$WC.Dispose(); 
+0

Dzięki .. Ale jak mogę pobrać $ viewstate i $ eventvalidation przed pocztą? Muszę opublikować wartość $ eventvalidation, aby post był skuteczny. Ponadto, jak dodać Useragent do postu? – MKANET

+0

Opublikowałem moją najlepszą próbę (w moim oryginalnym pytaniu) podczas konwersji mojego oryginalnego skryptu, aby korzystać z klienta internetowego. Potrzebuję jednak pomocy od kogoś, kto wykracza poza zwykłe kopiowanie i wklejanie ogólnego przykładu z google. – MKANET

4

Oto kod używam aby umieścić moje żądania sieci Web, nie jest to dokładna odpowiedź, ale przypuszczam, że można go przystosować:

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 
    } 
} 
1

Wygląda na to, że był bardzo blisko do uzyskania to działa. Z jakiegoś powodu musiałem też dodać __VIEWSTATE (oprócz __EVENTVALIDATION) w POST. Byłem w stanie to ustalić, weryfikując dane formularza za pomocą Fiddlera.

$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(); 
0

Jeśli nadal potrzebujesz skryptu do wielokrotnego użytku, możesz wykorzystać to, co napisałem, pod kątem podobnego problemu. Musiałem publikować tylko przy użyciu PowerShell 2.0. Skrypt jest dostępny w nice Reusable Function tutaj na GitHub: Request POST REST via Reusable Function

Powiązane problemy