To start this off, Slenium WebDriver is not an option due to it requiring approval to run and I am locked to the Windows environment. In addition, the site tool I am accessing is old and only works in Internet Exploder.
This script worked just "okay" in PowerShell 5.1 but I need to convert it to 7.1. I'm running into a few strange issues regarding the IE Com object and how I interact with it. I get the error code 0x800A01B6, which references "Execution Stopped" and before Microsoft nerfed the error output, the full error was:
Exception from HRESULT: 0x800A01B6
At line:1 char:1
+ ($ie.document.getElementsByName("email") |select -first 1).value = $u ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], NotSupportedException
+ FullyQualifiedErrorId : System.NotSupportedException
I previously bypassed this error by re-hooking the IE COM window through the Windows Shell, but now it's come back to haunt me. I can't seem to execute a single command series without re-hooking the window each time. It seems like a minor complaint, but would there be an issue re-hooking each time I wanted to run a JavaScript method? (Other than the script now getting more complex as I can't store ANYTHING in reference)
I tried the double-ampersand operator to see if it would help to queue commands in a single line, but no dice.
I have also tried getElementByID, but it gives me the same error message. I made sure to implement a method that waits for the browser to not be busy, but that seems to be where I'm failing. I have had this issue happen in the past when automating IE. While the program sleeps to wait for the browser to finish loading, something happens to where I'd have to re-hook the window.
I know that IE COM has some event triggers that can be registered, but I don't think I can do that from within PowerShell... (E.g. Onload)
Below is the relevant code and what I can provide:
$ie_list = [PSCustomObject]@{
url1 = "http://test-url1"
title1 = "INTER Net 1"
hwnd1 = $false
url2 = "http://test-url2"
title2 = "INTER Net 2"
hwnd2 = $false
url3 = "http://test-url3"
title3 = "INTER Net 3"
hwnd3 = $false
# First three internet, second three intranet
url4 = "http://test-url4"
title4 = "INTRA Net 1"
hwnd4 = $false
url5 = "http://test-url5"
title5 = "INTRA Net 2"
hwnd5 = $false
url6 = "http://test-url6"
title6 = "INTRA Net 3"
hwnd6 = $false
}
for ($num = 1; $num -le 6; $num++)
{
$ie_com = new-object -comobject InternetExplorer.Application
$ie_list."hwnd$num" = $ie_com.HWND
$hWnd = $ie_list."hwnd$num"
Write-Host "`nConnecting using URL $($ie_list."url$num")"
$ie_com.navigate2($ie_list."url$num")
Write-Host "Successfully created window $num with HWND $hWnd."
# We can wait for the page to finish loading all the way!
# If we did not release and re-hook, the object would null itself. Not cool.
# Manual release COM object
$ie_com = $false
# Re-integrate using Shell COM methods. This typically works a little better but not by much. It's still Internet Explorer.
$app = New-Object -Com shell.application
$ie_com = $app.Windows() | Where-Object {$_.HWND -match $hWnd -and $_.Name -match "Internet Explorer"} | Select-Object -Last 1
# Making sure it's still an object!
if ($ie_com -isnot [object] -or $ie_com.Document -isnot [object])
{
# Something done messed up.
Write-Host -ForegroundColor Red "FAILED to connect to Com Object $num at $hWnd."
# Pause
Continue
}
$doc = $ie_com.Document
Write-Host "`tReconnected COM object $num at $hWnd"
if ($ie_com.Busy -or $ie_com.ReadyState -ne 4)
{
Write-Host -NoNewline "Browser busy. Waiting"
$timeout = 0
while ($ie_com.Busy -and $ie_com.ReadyState -ne 4 -and $timeout -le 20)
{
Start-Sleep -Milliseconds 50
Write-Host -NoNewline "."
$timeout++
}
# Have to manually add linebreak
Write-Host " "
}
$u_fill = $false
$p_fill = $false
# In upgraded to Powershell 7, IHTML3 is not required for reliability when it was previously used in 5.1
# It's freakin weird. MS sucks.
Try {
$link = $doc.getElementsByName("j_username") | Select-Object -First 1 && $link.focus() && ($link.value = $env:USERNAME)
$u_fill = $true
}
Catch {
Write-Host -ForegroundColor Red "`tAn error occurred."
Write-Host -ForegroundColor Red "`t$_`n`t$($_.ErrorDetails)"
}
if ($false -eq $u_fill)
{
Write-Host -ForegroundColor Red "`tUnable to fill in Username. Skipping..."
Continue
}
Write-Host "`tUsername in window $num filled in"
Try {
$link = $doc.getElementsByName("j_password") | Select-Object -First 1 && $link.focus() && ($link.value = $pw)
$p_fill = $true
}
Catch {
Write-Host -ForegroundColor Red "`tAn error occurred."
Write-Host -ForegroundColor Red "`t$_`n`t$($_.ErrorDetails)"
}
if ($false -eq $p_fill)
{
Write-Host -ForegroundColor Red "`tUnable to fill in Password. Skipping..."
Continue
}
Write-Host "`tPassword in window $num filled in"
# No issues with this window. Pull the lever, Kronk!
$link = $doc.getElementsByName("input") | Where-Object { $_.value -eq "SIGN IN" } && $link.click()
Write-Host -ForegroundColor Green "`tLogin button in window $num clicked"
}
Output
Connecting using URL http://test-url1
Successfully created window 1 with HWND 921560.
Reconnected COM object 1 at 921560
Browser busy. Waiting..
An error occurred.
You cannot call a method on a null-valued expression.
Unable to fill in Username. Skipping...
Connecting using URL http://test-url2
Successfully created window 2 with HWND 1314278.
Reconnected COM object 2 at 1314278
Browser busy. Waiting..
An error occurred.
0x800A01B6
Unable to fill in Username. Skipping...
$ie_com = $false
for instance does NOT release the object.[System.Runtime.InteropServices.Marshal]::ReleaseComObject($ie_com)
but this doesn't seem to change the behavior. I looked at the UI automation and wasn't sure where to begin. Upon further reading, I think my object is being garbage collected? Default Marshaling Behavior