Can't download files with PowerShell IE COM Object [with login] - powershell

I have a script using PowerShells IE COM Object to login to a site and navigate to a page with PDFs (that I wish to download). I am using IE COM object to do all the navigation, and Invoke-WebRequest for the actual download. Issue is when the PDF files download they are size 2kb and can't be opened. I have a strong feeling this is a session issue and IE must be forgetting that I am logged in somehow. Any way to make IE remember I am logged in when so that I can download the files successfully?
Any help appreciated. Thanks.
Edit:
$ie = New-Object -COMObject InternetExplorer.Application
$ie.visible = $true
# Navigate to home page
$ie.navigate($URL)
while ($ie.Busy -eq $true){Start-Sleep -Seconds 3}
$Username = $ie.Document.getElementsByName("userName")
$Username.item(0).value = "username"
$Password = $ie.Document.getElementsByName("password")
$Password.item(0).value = "pass"
$AcceptTerms = $ie.Document.getElementById("useAddtnlField")
$AcceptTerms.checked = $true
$Btn = $ie.Document.getElementsByTagName("span") | ? {$_.title -match 'Login'}
$Btn.click()
while ($ie.Busy -eq $true){Start-Sleep -Seconds 2}
# ---- logged in ----
# -- Opens link in new window (due to JS) --
$ie.Navigate("https://chaseloanmanager.chase.com/Chaselock/ViewOnlineGuide.aspx")
while ($ie.Busy -eq $true){Start-Sleep -Seconds 2}
After that last navigate, I lose the $ie object and can no longer do anything with it. If I create a new $ie2 object, and continue the script using $ie2, the files are unable to be opened when finished. I was also unsuccessful getting access to the window using Shell.Application and Windows() method as to try and reference the original $ie window. Anyways, I think I need to complete the script using the original $ie object so that I am recognized as logged in throughout the process and can have a valid download at the end. Hopefully that makes sense and can help someone help me. Thanks

Related

Update GUI in Powershell

I want to write a programm which has a Kind of traffic light funtion. The color of the Frame should be changed depending on an check. I already solved the check of the criterias, so in this example the while-Loop is vicarious for a bigger check. But to focus on the problem i shortend it like this. My problem is that i canĀ“t update the Color of the UI.
So the program should be running all the time, but it seems to be stuck at:
[void] $Form.ShowDialog()
and only will continue after I close the form. So how can i bypass this section to get into the infinit Loop, so that my Form is shown all the time with changing Color?
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "Test"
$Form.Size = New-Object System.Drawing.Size(300,300)
$Form.StartPosition = "CenterScreen"
$Form.BackColor = "Green"
$Form.Topmost = $True
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
while ($True)
$test = Get-Content -Path C:\Users\admin\Documents\pro.txt
if ($test -eq 2)
{
$Form.BackColor = "Green"
} else {
$Form.BackColor = "Red"
}
Start-Sleep -s 2
}
Thanks for you help!
$Form.ShowDialog()
This line requires interaction on the form. The code following that line will not run until the form is closed. Another way to launch the form would be like the following
$Form.Show()
If you launch the form like that, the code should continue to run. Although you still may need a better solution, as your following code uses start-sleep -s 2. I believe this might also make your form sleep, which would render it potentially unusable.
I would recommend learning about PowerShell Event Handlers here. There might be a better solution using an event handler for your solution. An example of an event handler follows
$Form_Load {
# Your commands and stuff here #
}
The $Form is the object that the event is looking at, then you have a separator _, then Load is the name of the actual event that when executed the code runs. So any of the code inside those brackets will run right away when form $Form is launched. This can be anything from loading a form, clicking a button, or even a selected index changing inside of a listbox.
Event handlers took my PowerShell GUI building abilities to then next level when it comes to what I had the ability to do with the form. So I would highly recommend learning about event handlers if PowerShell GUIs are the normal for you, the most helpful tool you could buy is SAPIEN PowerShell Studio which is an extremely helpful development environment. It is basically a Visual Studio built just for PowerShell. I think it's in the $400-$500 range.

Running functions with COM objects in parallel

I have four sites which I have to check specific HTML for every so often and I'd like to automate this. I've tried to use Invoke-WebRequest but I couldn't figure out how to step through the pages since a lot of AJAX is being used. This is why I use two IE COM objects. With the COM objects I can easily step through and search for the correct HTML on each page.
The problem is that the checks run sequentially:
#Define functions
site1 { }
site2 { }
etc..
#run functions
$result = site1 #returns bool
$result = site2 #returns bool
etc..
I'd like to have the site checks run at the same time but I have been unable to do so with either Start-Job or a workflow.
I don't think I have figured out the syntax for either option as the Visible property from the IE COM object never triggers:
$url = "somesite.com"
$site = New-Object -COM InternetExplorer.Application
$site.Silent = $true
$site.Navigate($url)
while ($ie.ReadyState -ne 4) {Start-Sleep -m 500}
$site.Visible = $true
What is the proper way to have these site checks run at the same time and also have them be visible?

PowerShell: Using already created objects

$ie = New-Object -com internetexplorer.application
i want to reuse this object when the script runs next time. I don't want to create a new object
You should be able to attach to the process with this, check the result of the Windows() method, locate the IE one and then build the correct where clause:
$ie = (New-Object -ComObject Shell.Application).Windows() | Where-Object {...}

PowerShell IE9 ComObject has all null properties after navigating to webpage

I have a PowerShell script that navigates to a (presumably) classic ASP page on our intranet to stop a Windows Service running on our server as part of the deployment process for that service (and restarts it after deploying the new files). It ran fine until we recently upgraded to IE9. Here's the script.
# Open service page in IE
$ie = new-object -comobject InternetExplorer.Application
$ie.visible = $true
$ie.navigate($serviceUrl)
while($ie.busy) { start-sleep 1 }
# Stop service
$ie.Document.getElementById("dropDownActionList").value = "Stop"
$ie.Document.getElementById("buttonTakeAction").click()
while($ie.busy) { start-sleep 1 }
Now when I run the script, it successfully launches IE, but throws the following error:
You cannot call a method on a null-valued expression.
At C:\Projects\ABC\Scripts\Deploy.ps1:85 char:28
+ $ie.Document.getElementById <<<< ("dropDownActionList").value = "Stop"
+ CategoryInfo : InvalidOperation: (getElementById:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
When I investigate in PowerShell, I find that if I create the IE ComObject, it at first has valid properties, but as soon as I navigate to the the service control page, all the properties are null (almost as if the ComObject gone away?). For example, before the HWND property had a valid value, but now it's null ($ie.hwnd -eq $null returns true). No error is displayed in PowerShell when I navigate to the page.
I looked at some similar questions, but the first one doesn't match my circumstance (the Document property is null in my case) and as for the latter one, IE9 defaults to compatibility mode for intranet sites. I saved the ASP page and ran it through the w3c validator and it threw some errors (although none related to the elements I'm trying to deal with). Unfortunately I can't fix those. Other sites don't seem to have this problem. Any suspicions on what the problem may be and recommendations on work-arounds?
I just worked through this.. sort of. I was seeing the same behavior until I turned off protected mode in IE. This seems to have something to do with submitting from one security zone to the next. So.. assuming that your original page is in the internet zone, with protected mode on, you submit to a page in a trusted zone or intranet or whatever, it seems like the COM context is lost. Probably intentional. I'm going to try fixing the zones, and keeping protected mode on.
Hope this helps.
EDIT: This is also a non-issue if you run your powershell in elevated mode (run as admin)
In addition:
http://msdn.microsoft.com/en-us/library/bb625962.aspx
This problem is caused by integrity levels since Internet Explorer 8.
That is also the reason, why the application runs well as administrator.
Since IE-8 runs in "low integrity" mode, it is not possible to automate IE from within a script. This is because the script runs as an user which belongs to "medium integrity" mode. The security design is such that it can send instructions from medium to low integrity, but can not receive data from low to medium integrity.
Update: Here is a working example how to do it without changing any settings. It gets back the lost com-Object.
function ConnectIExplorer() {
param($HWND)
$objShellApp = New-Object -ComObject Shell.Application
try {
$EA = $ErrorActionPreference; $ErrorActionPreference = 'Stop'
$objNewIE = $objShellApp.Windows() | ?{$_.HWND -eq $HWND}
$objNewIE.Visible = $true
} catch {
#it may happen, that the Shell.Application does not find the window in a timely-manner, therefore quick-sleep and try again
Write-Host "Waiting for page to be loaded ..."
Start-Sleep -Milliseconds 500
try {
$objNewIE = $objShellApp.Windows() | ?{$_.HWND -eq $HWND}
$objNewIE.Visible = $true
} catch {
Write-Host "Could not retreive the -com Object InternetExplorer. Aborting." -ForegroundColor Red
$objNewIE = $null
}
} finally {
$ErrorActionPreference = $EA
$objShellApp = $null
}
return $objNewIE
}
$HWND = ($objIE = New-Object -ComObject InternetExplorer.Application).HWND
$objIE.Navigate("https://www.google.com")
$objIE = ConnectIExplorer -HWND $HWND

PowerShell to Open Outlook, Make Visible

My mission is to graduate from using PowerShell to create an instance of Outlook to simply viewing, or making visible the process that I can see in the TaskManager.
To Digress, this works for Word.Application
but not for Outlook.Application.
$MsApp = New-Object -comObject Word.Application
$MsApp.Visible = $true
I have checked the methods but cannot find a suitable verb to open, run or make visible.
I would be so grateful for a solution.
To activate a running Outlook that's just minimized:
[Runtime.InteropServices.Marshal]::GetActiveObject("Outlook.Application").ActiveWindow().Activate()
To create an Outlook instance that's visible (it's simplest to just start outlook.exe):
(new-object -com Outlook.Application).GetNamespace("MAPI").GetDefaultFolder("olFolderInbox").GetExplorer().Display()
To make the code clearer:
$outlook = new-object -com Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")
$folder = $namespace.GetDefaultFolder("olFolderInbox")
$explorer = $folder.GetExplorer()
$explorer.Display()
If you want to make visible an already running instance of Word or Outlook, you don't want to use New-Object. You want to get the running object. You can do this with a .NET call:
$word = [Runtime.InteropServices.Marshal]::GetActiveObject("Word.Application")
$word.Visible = $true