I'm trying to log into my printers to grab logs from them and parse them with powershell.
The logon box isn't a FORM, it's an unordered list containing INPUT textboxes.
So I have managed to select the PIN textbox and give it the correct value.
I have also managed to get a hold of the button I have to click, but now my problem is, I need to click that button and declare a SessionVariable so I can continue with that session once the button is clicked and I'm logged in.
How do I properly click this button? I'm trying this but it's not working:
$Page = Invoke-WebRequest -Uri "http://xxx/webglue/content?c=LoginDropdown&lang=fr"`
-Headers #{"Pragma"="no-cache"; "Accept-Encoding"="gzip, deflate"; "Accept-Language"="fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7"; "User-Agent"="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"; "Accept"="application/json, text/javascript, */*; q=0.01"; "Cache-Control"="no-cache"; "X-Requested-With"="XMLHttpRequest"; "Cookie"="lang=fr; autoLogin=false"; "Referer"="http://xxx/"}`
-ContentType "application/x-www-form-urlencoded; charset=utf-8"`
-SessionVariable "SESSION"
$TextboxPIN = $page.ParsedHtml.body.getElementsByTagName('input') | Where-Object {$_.OuterHTML -match "pin"}
$TextboxPIN.value = "xxx"
$ConnectionButton = $page.ParsedHtml.body.getElementsByTagName('button') | Where-Object {$_.onclick -like "*login(this)*"}
Invoke-WebRequest -Uri ("http://xxx/webglue/content?c=LoginDropdown&lang=fr"+ $ConnectionButton.click() ) -Method POST -Body $ConnectionButton -SessionVariable "ADMIN"
This doesn't work for now because i'm not properly logged in since I can't click the button correclty with POST
Invoke-WebRequest -uri "http://xxx/cgi-bin/history" -WebSession $ADMIN
That http:// PRINTER-IP/webglue/content?c=LoginDropdown&lang=fr"+ $BoutonConnexion.click() is based on how it's done with forms but i'm sure it's wrong in this case. How to properly click it?
After trying a lot of different things, none worked, here is how I ended up getting it working. It's not pretty but it works well and takes just a few seconds to extract all the logs, which I can then parse later.
This is for a Lexmark MS621n printer but could be adapted to other Lexmark printers.
This dumps all the log files I found of interest:
$Printer = "IPofPrinter"
$ie = New-Object -ComObject 'InternetExplorer.Application'
$ie.visible = $true
$ie.navigate("http://$printer")
do {start-sleep -m 100} until ($ie.ReadyState -eq 4)
$Menu = $ie.document.IHTMLDocument3_getElementById("loginclickarea")
$menu.Click()
start-sleep 1
$pin = $ie.document.IHTMLDocument3_getelementsbytagname("input") | Where-Object {$_.OuterHTML -match "pin"}
$pin.focus()
$wshell = New-Object -ComObject wscript.shell
$wshell.SendKeys("XXXXX")
$btn = $ie.document.IHTMLDocument3_getelementsbytagname("button") | Where-Object {$_.OuterHTML -like "*login(this)*"}
$btn.Click()
do {start-sleep -m 100} until ($ie.ReadyState -eq 4)
$ie.navigate("http://$printer/cgi-bin/enginedebugdata")
do {start-sleep -m 100} until ($ie.ReadyState -eq 4)
$ie.Document.documentElement.innerHTML > C:\TEMP\$($printer)_enginedebugdata.log
$ie.navigate("http://$printer/cgi-bin/eventlog_se")
do {start-sleep -m 100} until ($ie.ReadyState -eq 4)
$ie.Document.documentElement.innerHTML > C:\TEMP\$($printer)_eventlog.log
$ie.navigate("http://$printer/cgi-bin/history")
do {start-sleep -m 100} until ($ie.ReadyState -eq 4)
$ie.Document.documentElement.innerHTML > C:\TEMP\$($printer)_history.log
$ie.navigate("http://$printer/cgi-bin/se_net_details")
do {start-sleep -m 100} until ($ie.ReadyState -eq 4)
$ie.Document.documentElement.innerHTML > C:\TEMP\$($printer)_se_net_details.log
$ie.navigate("http://$printer/cgi-bin/netsetuppg")
do {start-sleep -m 100} until ($ie.ReadyState -eq 4)
$ie.Document.documentElement.innerHTML > C:\TEMP\$($printer)_netsetuppg.html
$ie.Stop()
$ie.Quit()
Related
I am trying to log on web page using PowerShell and generate some. Although Powershell ISE gives some errors, current script works okay(sometimes log on sometimes not) but last part seem doesn't work to generate the Report by clicking the "CSV" Button.
Any help please?
$username = "username"
$password = "password"
$ie = New-Object -ComObject InternetExplorer.Application
$ie.visible=$true
$ie.navigate("http://..../login")
while($ie.ReadyState -ne 4) {start-sleep -m 300}
$ie.document.IHTMLDocument3_getElementById('user_session_email').Value=$username
$ie.document.IHTMLDocument3_getElementById('user_session_password').Value=$password
$ie.Document.IHTMLDocument3_getElementById('commit').Click()
$ie.navigate("http://..../activity_reports")
while($ie.ReadyState -ne 4) {start-sleep -m 100}
$currentDate= (Get-Date).ToString('dd-MM-yyyy')
$ie.document.IHTMLDocument3_getElementById('from_date').innertext= $currentDate
$ie.document.IHTMLDocument3_getElementById('to_date').Value=$currentDate
$Link=$ie.Document.IHTMLDocument3_getElementByType('submit') | where-object {$_.class -eq 'btn
btn-default btn-sm'}
$Link.click()
Symantec recently changed their download page which moved to broadcom. Since then Invoke-WebRequest cannot grab the http url for the v5i64.exe file.
However the http url can be found when using Developer Tools in the browser looking at the Elements level, inside the body section of the page.
Does anyone have an idea on how this daily-changed url can be extracted with PowerShell?
$webreq = Invoke-WebRequest "https://www.broadcom.com/support/security-center/definitions/download/detail?gid=sep"
$webreq.Links | Select href
Use IE via ComObject
$ie = new-object -ComObject "InternetExplorer.Application"
$ie.visible=$True
while($ie.Busy) { Start-Sleep -Milliseconds 100 }
$IE.navigate2("https://www.broadcom.com/support/security-center/definitions/download/detail?gid=sep")
while ($IE.busy) {
start-sleep -milliseconds 1000 #wait 1 second interval to load page
}
Then find elementy by $ie.Document.IHTMLDocument3_getElementsByTagName("element name")
The following PowerShell script will prompt you to download the links containing the text v5i64.exe and HTTPS. This works on PowerShell 5.1 for Windows. It does not work for PowerShell 6 or 7 (PowerShell Core).
Tested on Windows 10.0.18363.657, Internet Explorer 11.657.18362, PowerShell 5.1.18362.628
$url = "https://www.broadcom.com/support/security-center/definitions/download/detail?gid=sep"
$outfile = "./v5i64.exe"
$ie = New-Object -ComObject "InternetExplorer.Application"
$ie.visible=$True
while($ie.Busy) {
Start-Sleep -Milliseconds 100
}
$ie.navigate2($url)
while($ie.ReadyState -ne 4 -or $ie.Busy) {
Start-Sleep -milliseconds 500
}
$ie.Document.getElementsByTagName("a") | % {
if ($_.ie8_href -like "*v5i64.exe") {
if ($_.ie8_href -like "https://*") {
$len = (Invoke-WebRequest $_.ie8_href -Method Head).Headers.'Content-Length'
Write-Host "File:" $_.ie8_href
Write-Host "Size:" $len
$confirm = Read-Host "Download file? [y/n]"
if ($confirm -eq "y") {
Write-Host "Downloading" $_.ie8_href
Invoke-WebRequest -Uri $_.ie8_href -OutFile $outfile
}
}
}
}
$ie.Stop()
$ie.Quit()
thanks for the proposed solutions. However here is my final code I am using:
$SEP_last_link = ("http://definitions.symantec.com/defs/"+($SEP_last | Select-String release -NotMatch | select -Last 1))
$Symantec_folder = "C:\Download for DVD\Symantec"
$Symantec_filepath = "$Symantec_folder\$SEP_last"
if (!(Test-Path "$Symantec_filepath" -PathType Leaf)) {
Write-Host "`rStart to download Symantec $SEP_last file: $(Get-Date)`r"
$start_time = (Get-Date)
$webclient = New-Object System.Net.WebClient
$WebClient.DownloadFile($SEP_last_link, $Symantec_filepath)
Write-Host "`r$SEP_last file has been downloaded successfully`r" -ForegroundColor Green
$end_time = $(get-date) - $start_time
$total_time = "{0:HH:mm:ss}" -f ([datetime]$end_time.Ticks)
Write-Host "`rTime to download Symantec $SEP_last file: $total_time`r"
} else {
Write-Host "`rSymantec $SEP_last file already exists!`r" -ForegroundColor Yellow
}
Get-ChildItem -Path "$Symantec_Folder\*-v5i64.exe" -Exclude "$SEP_last" -Verbose –Force | Remove-Item
My company wants me to grab data from their internal website, organize it, and send it to a database. The data is displayed on tables that you navigate to within the site. I'm wanting to pull the fields into a file or memory for further processing.
So far, I can log into the site in powershell by getting the submit login button's ID, and passing my username/password. I'm able to pass use the navigate method to change the page to the appropriate page within the site. However, running an Invoke-WebRequest on the new page, as well as using the Net.WebClient on the new page is returning the information found on the original site's login screen(I know, because nothing from the table makes it into the returned values, regardless of the commands I use). The commented code is what I've tried previously.
Here is the code-minus the values of my id/password/site link
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ie = New-Object -ComObject 'internetExplorer.Application'
$ie.Visible= $true # Make it visible
$username="myid"
$password="mypw"
$ie.Navigate("https://webpage.com/index.jsp")
While ($ie.Busy -eq $true) {Start-Sleep -Seconds 3;}
$usernamefield = $ie.document.getElementByID('login')
$usernamefield.value = "$username"
$passwordfield = $ie.document.getElementByID('password')
$passwordfield.value = "$password"
$Link = $ie.document.getElementByID('SubmitLogin')
$Link.click()
$url = "https://webpage.com/home.pa#%5BT1%2CM181%5D"
$ie.Navigate($url)
While ($ie.Busy -eq $true) {Start-Sleep -Seconds 3;}
$doc = $ie.document
$web = New-Object Net.WebClient
$web.DownloadString($url)
#$r = Invoke-WebRequest $url
#$r.Forms.fields | get-member
#$InnerText = $r.AllElements |
# Where-Object {$_.tagName -ne "TD" -and $_.innerText -ne $null} |
# Select -ExpandProperty innerText
#write-host $InnerText
#$r.AllElements|Where-Object {$_.InnerHtml -like "*=*"}
#$doc = $ie.Document
#$doc.getElementByID("ext-element-7") | % {
# if ($_.id -ne $null){
# write-host $_.id
# }
#}
$ie.Quit()
I obviously don't have your page and can't ensure that the body of the POST from signing in contains the fields login and password so that will require some trial & error from you. As a mini-example, if you open up your console dev tools network tab and filter by POST, you can observe how your login page signs you in. When I open reddit to sign in, it sends a POST to https://www.reddit.com/login with a body containing a username and password key/value (both plaintext). This action sets up my browser session to persist my login.
Here's a code example that uses the HtmlAgilityPack library to interact with the resulting page as if it were XML.
Enabling TLS1.2:
[System.Net.ServicePointManager]::SecurityProtocol =
[System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12
Setting up your web session:
$iwrParams = #{
'Uri' = 'https://webpage.com/index.jsp'
'Method' = 'POST'
'Body' = #{
'login' = $username
'password' = $password
}
'SessionVariable' = 'session'
# avoids cases where IE has not been opened
'UseBasicParsing' = $true
}
# don't care about response - only here to initialize the session
$null = Invoke-WebRequest #iwrParams
Getting the protect page content:
$iwrParams = #{
'Uri' = 'https://webpage.com/home.pa#%5BT1%2CM181%5D'
'WebSession' = $session
'UseBasicParsing' = $true
}
$output = (Invoke-WebRequest #iwrParams).Content
Downloading/adding HtmlAgility:
if (-not (Test-Path -Path "$PSScriptRoot\HtmlAgilityPack.dll" -PathType Leaf))
{
Invoke-WebRequest -Uri https://www.nuget.org/api/v2/package/HtmlAgilityPack -OutFile "$PSScriptRoot\html.zip"
Expand-Archive -Path "$PSScriptRoot\html.zip" -DestinationPath "$PSScriptRoot\html" -Force
Copy-Item -Path "$PSScriptRoot\html\lib\netstandard2.0\HtmlAgilityPack.dll" -Destination "$PSScriptRoot\"
Remove-Item -Path "$PSScriptRoot\html", "$PSScriptRoot\html.zip" -Recurse -Force
}
Add-Type -Path "$PSScriptRoot\HtmlAgilityPack.dll"
$html = [HtmlAgilityPack.HtmlDocument]::new()
Loading/parsing your page content:
$html.LoadHtml($output)
# do stuff with output.
$html.DocumentNode.SelectNodes('//*/text()').Text.Where{$PSItem -like '*=*'}
Footnote
I made the assumption in the code you were executing from a script where $PSScriptRoot will be populated. If it's being run interactively, you can use the $pwd automatic variable instead (carry-over from *nix, print working directory). This code requires PSv5+.
After some serious effort-I managed to get the pages to work correctly. Turns out I wasn't waiting for everything to load-but once I had that, I eventually found the correct tag/name to make everything work.
Assuming the code in the original post is correct up to "ie.Navigate($url)"
$ie.Navigate($url)
While ($ie.Busy -eq $true) {Start-Sleep -Seconds 3;}
$r = Invoke-WebRequest $url
$doc = $ie.document
$j = ($doc.getElementsByTagName("body") | Where {$_.className -eq 'thefullclassname found in the quotes of <body class="" of the area you wanted'}).innerText
write-host $j
This gave me the output of a very annoyingly done table that isn't a "table", and has the first row/col on it's own-so formatting the output to an easy to use version will be the new hassle. At least I got everything on the page that had the text I needed...so progress!
I am working on a powershell script, which should fill an IE form, but it doesn't send the value to the form, instead, it just writes the value ("search text") into the Powershell script..?
I have copied my code from this post:
Filling web form via PowerShell does not recognize the values entered
But I don't need to open a new IE window, I need to use an existing IE window, which is already open, before I start the ps script.
My code (for your info,"lst-ib" is the id of google.at's search field):
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic")
$app = new-object -com shell.application
$ie = $app.windows() | where {$_.Type -eq "HTML Document"}
$ie.visible = $true;
while($ie.Busy) { Start-Sleep -Milliseconds 100 }
$ie.document.IHTMLDocument3_getElementById("lst-ib").focus()
Start-Sleep -Milliseconds 1000;
[System.Windows.Forms.SendKeys]::Sendwait("test searchtext");
As for this...
But I don't need to open a new IE window, I need to use an existing IE
window, which is already open, before I start the ps script.
What / who opens this?
You have to discover what wind this is, in case of more that one IE session / tab is open.
You have to call the from object explicitly to act on the.
You also are using elements that don't really exist with what you are doing.
Since we cannot access you site, here is an example I provided a while back to someone have issues interacting with the aircanada site.
Now that site is a bite funky, as it is a mult-page site, with language popups recently added, I don't deal with the language popup in this example, so, just click past that manually, since I've not updated the code to deal with it. Once you click past that, that form will fill that values passed in.
You will note I am not using sendkeys for any of the page interactions. I am just using the from elements and passing in what values I want. Now this does open a new window for this due to the URL. Where as your code needs to look for that window first.
# Check from elements for the multi-page site
$url = 'https://www.aircanada.com/ca/en/ado/profile/sign-in.html'
($FormElements = Invoke-WebRequest -Uri $url -SessionVariable fe)
($FormElements = Invoke-WebRequest -Uri $url -SessionVariable fe).Forms
($Form0 = $FormElements.Forms[0]) | Format-List -Force
$Form0.Fields
($Form1 = $FormElements.Forms[1]) | Format-List -Force
$Form1.Fields
($Form2 = $FormElements.Forms[2]) | Format-List -Force
$Form2.Fields
$SiteSource = Invoke-WebRequest -Uri $url
$SiteSource.AllElements | Where{$_.TagName -eq "Button"} `
| Select-Object -Expand InnerText
$SiteSource.AllElements | Where{$_.TagName -eq "Button"} `
| Select-Object -Property * | Where innerText -eq 'SIGN IN'
So armed with the above, you get to do this.
# Navigate to aircanada
$url = 'https://www.aircanada.com/ca/en/ado/profile/sign-in.html'
# Instantiate IE
$ie = New-Object -com internetexplorer.application
$ie.visible = $true
$ie.navigate($url)
# Wait for IE to load
while ($ie.Busy -eq $true) { Start-Sleep -Seconds 1 }
# Take needed actions on the air canada site. Fill out the site page
($ie.document.getElementById('agencyIATA') | Select-Object -first 1).value = '1234567'
($ie.document.getElementById('agencyID ') | Select-Object -first 1).value = '789'
($ie.document.getElementById('bookingAgent') | Select-Object -first 1).value = '159'
($ie.document.getElementById('password') | Select-Object -first 1).value = '1234'
($ie.document.getElementById('rememberAgencyInfo') | Select-Object -first 1).value = $true
# Start-Sleep -Seconds 2
# ($ie.Document.IHTMLDocument3_getElementsByTagName('button') `
# | Where-Object innerText -eq 'SIGN IN').Click()
All this being said, see also:
Controlling Internet Explorer object from PowerShell
https://blogs.msdn.microsoft.com/powershell/2006/09/10/controlling-internet-explorer-object-from-powershell
Here is the batch code:
<# :
#echo off
powershell /nop /ex bypass^
"&{[ScriptBlock]::Create((gc '%~f0') -join [Char]10).Invoke()}"
exit /b
#>
$ie = new-object -comobject InternetExplorer.Application
$ie.Visible = $false
$ie.Silent = $true
while($ie.Busy -ne $false) {start-sleep -m 100}
$ie.Navigate2("https://www.google.ru/", 4)
while($ie.Busy -ne $false) {start-sleep -m 100}
while($ie.ReadyState -ne 4) {start-sleep -m 100}
start-sleep -m 500
$ie.Stop()
echo $ie.Document.body.innerHTML > ".\html.txt"
$ie.Quit()
This code works fine in Windows 7 x64, Windows 8 x64, but not work in Windows 10 x64. Microsoft EDGE browser is not using, IE 11 is selected as default browser. I tried to run bat-file as administrator and as invoker.. What is wrong? Thanks for your help!
If you only need to retrieve the HTML content of a web page, don't use a web browser at all. Instead, use invoke-webrequest and access the content property of the resulting object.
invoke-webrequest -Uri http://www.google.ru/ | select-object -property content