-websession

Unfortunately, I don’t have the script now since I’m home. I’ll post it tomorrow.

My question is, I’m logging int a website using invoke web-request. I’m able to successfully login to the website. My problem is that, when I go to a url, it thinks I’m not logged in. I’m using the same session variable to login and to go to the specific page.

 

So, you’re use IVR in a script and then manually going to the web site via your browser?

That’s two completely different web sessions, one from the script and one from a browser. Since all site are https (well, almost all) these days. All SSL session are unique.

Outside of your script, you need to explain what you are trying to do.

No, I’m logging in and going to the part of the website from PowerShell using the same websession name.

This is the screenshot showing I’m logged in, but I can’t go the part of the website to upload some files.

https://drive.google.com/open?id=18tr4aBxTkroQKl1E1SOAEyeJ70LH2LC0

$Global:organization = Read-Host "`tEnter the organization"
$username = Read-Host "`tEnter the username"
$password = Read-Host "`tEnter the password"

$form.fields["organization"] = $organization
$form.fields["Username"] = $username
$form.fields["Password"] = $password

$Global:loginResponse = Invoke-WebRequest -uri ("https://dealer.md-bmc.rpdss.com/" + $form.Action) -WebSession $login -Method post -Body $form.Fields

if ($loginResponse.ParsedHtml.title -eq "RAPID Dealer Reporting Site") {
	Write-Host "`tLog in failed, please try again! `n" -ForegroundColor Red
}

else {
$info = $loginResponse.AllElements | where {$_.tagName -contains "span"}
$account = ($info.innerhtml | Select-Object -First 3).ToUpper()
Write-Host "`tLogged in as" $account "`n" -ForegroundColor Green
$upload = $loginResponse.AllElements.InnerHtml | Where-Object {$_ -match 'url="(administration/uploadprofileselector.aspx\?.*?)"'} |ForEach-Object {$matches[1]} | Select-Object -First 1

$uid = ($upload -replace '\D').Substring(0,4)
$oid = ($upload -replace '\D').Substring(4,6)

#this is where it "forgets" that it's already logged in.

$fileUploadurl = "https://dealer.md-bmc.rpdss.com/bwident/pawnshop/administration/uploadprofileselector.aspx?l=English&uid=$uid&oid=$oid"
$fileUploadPage = Invoke-WebRequest -Uri $fileUploadurl -WebSession $login

#this should be showing me a selection menu, but it's asking me to login again.  Please see screenshot.
$fileUploadPage.ParsedHtml.body.innerText
}

Any suggestions?

In your script, you have the $login variable as a value for the WebSession parameter, however you didn’t first declare it as a session variable.

Try executing this first to create the $login variable:

$Global:loginResponse = Invoke-WebRequest https://dealer.md-bmc.rpdss.com/ -Sessionvariable login

Rarely have I seen then need for global:*.

There are articles that cover why you not want to. Not saying that that one can’t or there is never a reason to, but…

As per Don Jones, ms powershell mvp and curator of this site...

I’m not personally a big fan of polluting the global scope just for one function’s benefit. Probably a preferred route would be to put your function in a script module, and then in that module export the function along with a module-level variable. That variable will be global while the module is loaded, but since it’s an explicit part of the module then the shell will be able to clean it up when removing the module.

powershell.org/forums/topic/global-variable-and-functions/#.W2zSI-SpVa0


Be sure to go back and review the help files which details scoping,

'docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes'
and or this article.
First rule of PowerShell scoping rules…

The keen observer will immediately notice that $globalvariable never produces any output. That is because a variable in PowerShell is not global unless you specifically says so by using $global:globalvariable. Always. At every use. So what is the scope of $globalvariable in our example? It’s ‘local’, local to the global scope to be precise. Unless specified otherwise nothing is ever global.

Note that you cannot just assign a value to $globalvariable, that would just create a local variable of that name shadowing the parameter. You are passing a reference object, so you have to use the value property.

sapien.com/blog/2013/03/06/first-rule-of-powershell-scoping-rules

I actually have a -Sessionvariable login. This is my whole script.

$menuChoice = $null
$webSite = "https://dealer.md-bmc.rpdss.com/default.aspx"
$year = (Get-Date).Year
$month = (Get-Date).Month
if ($month -lt "10") {
    $month = "0" + $month
}
$metalsXML = Get-ChildItem "\\ARG-040538\c$\BWI\XML"
$vincheckXML = Get-ChildItem "\\ARG-040538\c$\BWI\XMLNew\Vincheck"

function loginToRAPID() {    
    $Global:access = Invoke-WebRequest -uri $webSite -SessionVariable login
    $form = $access.forms[0]    
    $Global:organization = Read-Host "`tEnter the organization"
    $username = Read-Host "`tEnter the username"
    $password = Read-Host "`tEnter the password"
    $form.fields["organization"] = $organization
    $form.fields["Username"] = $username
    $form.fields["Password"] = $password    
    $Global:loginResponse = Invoke-WebRequest -uri ("https://dealer.md-bmc.rpdss.com/" + $form.Action) -WebSession $login -Method post -Body $form.Fields                       
}

function uploadXML() {          

    if ($loginResponse.ParsedHtml.title -eq "RAPID Dealer Reporting Site") {
        Write-Host "`tLog in failed, please try again! `n" -ForegroundColor Red        
    }    

    else {        
        $info = $loginResponse.AllElements | where {$_.tagName -contains "span"}
        $account = ($info.innerhtml | Select-Object -First 3).ToUpper()
        Write-Host "`tLogged in as" $account "`n" -ForegroundColor Green 
        $upload = $loginResponse.AllElements.InnerHtml | Where-Object {$_ -match 'url="(administration/uploadprofileselector.aspx\?.*?)"'} | 
            ForEach-Object {$matches[1]} | Select-Object -First 1 

        $blankIEPages = Get-Process | Where-Object {$_.MainWindowTitle -eq "Navigation Canceled - Internet Explorer"}
        Stop-Process -Id $blankIEPages.Id -Force

        $uid = ($upload -replace '\D').Substring(0,4)
        $oid = ($upload -replace '\D').Substring(4,6)        

        $global:fileUploadurl = "https://dealer.md-bmc.rpdss.com/bwident/pawnshop/administration/uploadprofileselector.aspx?l=English&uid=$uid&oid=$oid"

        $fileUploadPage = Invoke-WebRequest -Uri $fileUploadurl -WebSession $login

        $fileUploadPage.ParsedHtml.body.innerText
    }
}

function createFolders() {
    $metalsFolder =$metalsXML.name
    if($metalsFolder -notcontains $location) {
        $newFolder = New-Item -Path "\\ARG-040538\c$\BWI\XML\" -ItemType Directory -Name $location -Force        
        Write-Host "`tCreated new folder" $newFolder.FullName "`n" -ForegroundColor Green
        }      
}

function checkFolders() {     
    if ($organization -eq "united") {
        $location = "UIM"
        createFolders                      
    }
    elseif ($organization -eq "uime") {
        $location = "UIME"
        createFolders
    }
    elseif ($organization -eq "montgomeryscrap") {
        $location = "MSC"
        createFolders
    }
}

function runMain() {
    loginToRAPID
    uploadXML
    #checkFolders
}

while($menuChoice -ne '4') {

    switch ($menuChoice) {
        1 {runMain}
        2 {runMain}
        3 {runMain}
    }        
    
    Write-Host "[1] Transmit United Iron & Metal (UIM)"
    Write-Host "[2] Transmit United Iron & Metal East (UIME)"
    Write-Host "[3] Transmit Montgomery Scrap Company (MSC)"    
    Write-Host "[4] Quit program"    
    $MenuChoice = Read-Host "`nPlease select an option and press ENTER" 
}

I noticed that if I do this, I get what I want.

function loginToRAPID() {    
    $Global:access = Invoke-WebRequest -uri $webSite -SessionVariable login
    $form = $access.forms[0]    
    $Global:organization = Read-Host "`tEnter the organization"
    $username = Read-Host "`tEnter the username"
    $password = Read-Host "`tEnter the password"
    $form.fields["organization"] = $organization
    $form.fields["Username"] = $username
    $form.fields["Password"] = $password    
    $Global:loginResponse = Invoke-WebRequest -uri ("https://dealer.md-bmc.rpdss.com/" + $form.Action) -WebSession $login -Method post -Body $form.Fields  

    $fileUploadPage = Invoke-WebRequest -Uri https://dealer.md-bmc.rpdss.com/bwident/pawnshop/administration/uploadprofileselector.aspx?l=English"&"uid=4460"&"oid=771123 -WebSession $login

    $fileUploadPage.ParsedHtml.body.innerText  
}

Why can’t I put

$fileUploadPage = Invoke-WebRequest -Uri https://dealer.md-bmc.rpdss.com/bwident/pawnshop/administration/uploadprofileselector.aspx?l=English"&"uid=4460"&"oid=771123 -WebSession $login

    $fileUploadPage.ParsedHtml.body.innerText

in the uploadXML() function?

It’s a variable scoping issue. Your login variable only exists within the loginToRAPID() function. It is not returned, and it is does not have a global or script scope, so when the loginToRAPID() function ends, the $login variable that was set within the function goes away. When you subsequently call the uploadXML() function and try to use the $login variable, it is a null value because it has not been set within the working scope of the uploadXML() function.

how can I fix it? That’s what I can’t figure out. I know If I get rid of th functions it will work, but I like to use function if possible.

 

How do I return?

Here is a sample of the problem

Function a {
$aVar = "FunctionA"
"Output in function: $avar" | Out-Host
}

a

"Output outside of function: $avar" | Out-Host

Results:

Output in function: FunctionA
Output outside of function: 

The most appropriate way to handle it is to return the value from the function.

Function b {
$bVar = "FunctionB"
$bVar
}

$return = b

"Output outside of function: $return" | Out-Host

Results

Output outside of function: FunctionB

But you can also change the scope of the variable. (The following methods are not considered good practice)

Function c {
$script:cVar = "FunctionC"
"Output in function: $cvar" | Out-Host
}

c

"Output outside of function: $cvar" | Out-Host

Results

Output in function: FunctionC
Output outside of function: FunctionC
Function d {
$global:dVar = "FunctionD"
"Output in function: $dvar" | Out-Host
}

d

"Output outside of function: $dvar" | Out-Host

Results

Output in function: FunctionD
Output outside of function: FunctionD

 

Here is a more complete example using two functions. The variable gets set in one function and is returned to the script. The script then passes the returned value into the second function as a parameter.

Function e {
    $evar = "Variable Set in Function E"
    "`$evar inside of Function E: $evar" | Out-Host
    $evar
}

Function f {
    Param (
        $evar
    )
    "`$evar inside of Function F (after being passed in as a parameter from main script): $evar" | Out-Host
}

$result = e
"`$evar in main script: $evar" | Out-Host
"`$result in main script: $result" | Out-Host

f -evar $result

Results:

$evar inside of Function E: Variable Set in Function E
$evar in main script:
$result in main script: Variable Set in Function E
$evar inside of Function F (after being passed in as a parameter from main script): Variable Set in Function E

 

Thank you, I’ll try those recommendations