InternetExplorer.Application COM object's getElementById method not working - powershell

I am very new to powershell, and I am trying to automate a login to website, I have browsed many examples but NONE is working without errors.
For example with this very simple script:
$ie = New-Object -comobject InternetExplorer.Application
$ie.Visible = $true
$ie.Navigate($URL)
$ie.Navigate("www.facebook.com")
$ie.document.getElementById("pass")
$ie.document.getElementById("pass").value = "Hi"
I am supposed to get "Hi" in the password field but I get instead this
I am getting this error in ALL the examples I found, what's going on? Is this something no longer supported in Powershell?
I have windows 10.

Don't use getElementById. Use IHTMLDocument3_getElementById, e.g.:
$ie.Document.IHTMLDocument3_getElementById("email").value = "asd123"
You can do this for other methods as well, such as IHTMLDocument3_getElementsByName.
I should add that I don't know why this works - I just used the following query to find any useful looking members on the Document object and played around with them
$ie.Document | Get-Member | where Name -like '*get*'

Related

Powershell - Can't figure out how to get web content from IE object

I am pretty new to Powershell and just using it for personal stuff. I have been experimenting with pulling specific info from websites to include in emails to family. By reading the forums I got pretty good using the Invoke-WebRequest cmdlet, but soon hit upon its limitation of not having access to content constructed dynamically at the time the page is loaded.
Thanks to these forums, I then discovered the IE object and how to pull the data. I had luck with one website, but another I tried does not work the same. Hoping for a little help figuring it out.
Here is a snippet of the inspected code for the page, with my target of interest highlighted.
Below is the code where I am trying to extract that text string. I have tried many iterations and approaches with no success. What is odd, though, the $ie.Document object supposedly has a "body" object, but when I tried to access it, I get a null object error. I notice the Document object itself has a getElementsByTagName method, so I tried that. It does not have a getElementsByClassName method.
Note that the URL I am loading is "https" so I am wondering if this is causing issues. Suggestions appreciated! If I can just get a surrounding chunk of the HTML, I am fine doing some string manipulation to get what I want.
# Create IE object and load URL
$WeatherURL = "https://weather.com/weather/today/l/77630"
$ie = New-Object -comobject "InternetExplorer.Application"
$ie.visible = $true
$ie.navigate($WeatherURL)
# Wait for the page to load
while ($ie.Busy -eq $true -Or $ie.ReadyState -ne 4) {Start-Sleep 2}
$Doc = $ie.Document
$Weather0 = $Doc.getElementsByTagName('span') `
| ?{$_.getAttribute('class') -eq "today-wx-descrip"} | Select-Object -First 1
You should replace
$Weather0 = $Doc.getElementsByTagName('span') `
| ?{$_.getAttribute('class') -eq "today-wx-description"} | Select-Object -First 1
With
$Weather0 = $Doc.getElementsByTagName('span') `
| ?{$_.getAttribute('class') -eq "today-wx-descrip"} | Select-Object -First 1
Note today-wx-description vs today-wx-descrip.

Modify the array text condition in an Outlook rule with PowerShell?

I work on a team, who manage a few hundred servers. We each take primary responsibility for about 100 servers. I am the new person on the team, so I have a rule "MyServers" in outlook that makes a special sound and moves emails in to the folder "MyServers", when an email comes in with the name of one of my servers in the subject or body. Servers come and go, and the responsible person changes occasionally. I can use the GUI to modify the list, but what I want to do is use PowerShell to modify the list of servers based on a data set from a SQL query on our table of whom belongs to what. (also would be helpful when covering for someone else.)
Per PowerShell - Managing an Outlook Mailbox with PowerShell, By Joe Leibowitz, March 2013 it is possible in theory. That article and the post Hey, Scripting Guy! How Can I Tell Which Outlook Rules I Have Created? December 15, 2009 by ScriptingGuy1 have taught me how to get outlook files into PowerShell to read and or write. The post Multiple Actions for one Outlook rule in Powershell has also been helpful.
I can find several examples of creating rules, mostly around email addresses. As I did more research (below) it seems like the I want to modify 'TextRuleCondition.Text' but I am not finding any example code that gets in to reading OR modifying rule conditions for a single existing rule.
Specifying Rule Conditions
TextRuleCondition Object (Outlook)
TextRuleCondition.Text Property (Outlook)
Optimally: I would like to go to the "MyServers" rule and change the array, from what it is to a new array that I will build with PowerShell, after getting the list from a SQL table.
##source https://blogs.technet.microsoft.com/heyscriptingguy/2009/12/15/hey-scripting-guy-how-can-i-tell-which-outlook-rules-i-have-created/
## Gets outlook rules on PC
#Requires -version 2.0
Add-Type -AssemblyName microsoft.office.interop.outlook
$olFolders = “Microsoft.Office.Interop.Outlook.OlDefaultFolders” -as [type]
$outlook = New-Object -ComObject outlook.application
$namespace = $Outlook.GetNameSpace(“mapi”)
$folder = $namespace.getDefaultFolder($olFolders::olFolderInbox)
$rules = $outlook.session.DefaultStore.<Some code here gets TextRuleCondition.Text for just MyServers>
$rules ## this displays the current value
##More code inserts the array that I built earlier (not actually built, yet as I don't know what it should look like)
$rules.Save() ## this saves the changes.
Everything I have found so far programmatically creates an entire new rule from PowerShell. Nothing indicates if it is, or is not possible to modify an existing rule. My Plan "B" would be to read the existing "MyServers" rule, modify the array, and overwrite the old rule with a new one. This is problematic as it limits options, only some conditions and actions can be created programmatically.
#setup
Add-Type -AssemblyName microsoft.office.interop.outlook
$olFolders = “Microsoft.Office.Interop.Outlook.OlDefaultFolders” -as [type]
$outlook = New-Object -ComObject outlook.application
$namespace = $Outlook.GetNameSpace(“mapi”)
#get all of the rules
$rules = $outlook.Session.DefaultStore.GetRules()
#get just the rule I care about
$myRule = $rules | ? { $_.Name -eq 'My Awesome Rule' }
#build my new array of text conditions
$textValues = #('ServerA', 'NewServerB')
#replace the existing value on my rule (this is assuming you are using BodyOrSubject, you can substitute Body, Subject, etc)
$myRule.Conditions.BodyOrSubject.Text = $textValues
#save all the rules
$rules.save()

COM InternetExplorer.Application Behavior

Been wrestling with parsing the HP Warranty website since the web service method seems to be constantly changing.
Problem I am having is I have tried to use the internet explorer com and its acting different depending on a version difference somewhere either PS or IE of which I am not certain how to tell.
Here is my core portion of code that I am testing with. You would need to find an HP Serial Number to test with.
$SerialNumber = ""
$link = "http://h20564.www2.hp.com/hpsc/wc/public/find?rows%5B0%5D.item.serialNumber=" + $SerialNumber + "&rows%5B0%5D.item.countryCode=US&submitButton=Submit"
Write-Verbose "Calling: $link"
$request = New-Object System.Net.WebClient
$request.UseDefaultCredentials = "True"
$request.Proxy = [System.Net.GlobalProxySelection]::GetEmptyWebProxy()
$results = $request.downloadstring($link)
if($results -match "Base Warranty") {
Write-Verbose "Results contain Warranty Data"
$results | Out-File "C:\Temp\Warranty.html" -Encoding ascii
$oIE = New-Object -ComObject InternetExplorer.Application
$oIE.Navigate("C:\Temp\Warranty.html")
$ohtmldoc = $oIE.Document
$rows = $ohtmldoc.documentElement.getElementsByClassName("hpui-normal-row")
$data = $rows[0].ChildNodes | ? {$_.TagName -eq "td"}
$ExpireDate = Date($data[4].InnerText)
} else {
Write-Verbose "Results do not contain Warranty Data"
$ExpireDate = ""
}
Works fine on my win 10 machine with IE11 v11.212.10586.0; PSVersion 5.0
Failing win 2008 R2 Term servers with IE11 v11.0.9600.17873CO in two different fashions; PSVersion 4.0
It appears that the DOM is not populating the ChildNodes property from the $rows[0] variable after it parses the ClassName.
Aside from the above being my main issue,
Another 2008 R2 Term server as soon as I invoke the $oIE.Navigate Method it opens an instance of an IE window for the link being called then the rest of the commands fail which I haven't seen happen yet on my other two environments.
Any thoughts would be greatly appreciated as I don't often use the InternetExplorer.Application COM. I really just need to be able to parse this HTML content to get the table data effectively. I had tried ditching the COM and ingesting the HTML contents as XML but HP has several malformed lines on the page this warranty result kicks back.

Set Multi-User Field in Sharepoint using Powershell and TaskManager

Im using the following to set/update a multi user field in Sharepoint using Powershell:
[Microsoft.SharePoint.SPFieldUserValueCollection]$lotsofpeople = New-Object Microsoft.SharePoint.SPFieldUserValueCollection
$user1 = $w.EnsureUser("domain\user1");
$user1Value = New-Object Microsoft.SharePoint.SPFieldUserValue($w, $user1.Id, $user1.LoginName)
$user2 = $w.EnsureUser("domain\user2");
$user2Value = New-Object Microsoft.SharePoint.SPFieldUserValue($w, $user2.Id, $user2.LoginName);
$lotsofpeople.Add($user1Value);
$lotsofpeople.Add($user2Value);
$i["lotsofpeoplefield"] = $lotsofpeople;
$i.SystemUpdate($false);
This works great in the PS Editor but as soon as I set this up as a repeating task in Win TaskManager, it fails for all items, where SPFieldUserValueCollection contains more than 1 user. Error: "Invalid look-up value. A look-up field contains invalid data. Please check the value and try again."
Any ideas?
Had the same problem today and it took me some time to solve it.
An explicitly cast solved the problem for me:
$i["lotsofpeoplefield"] = [Microsoft.SharePoint.SPFieldUserValueCollection] $lotsofpeople
$i.SystemUpdate($false);

Powershell accessing an object in AD SearchResultCollection

I have the following Powershell code:
$directorySearcher = New-Object System.DirectoryServices.DirectorySearcher
$directorySearche.PageSize = 100
$directorySearcher.SearchScope = [System.DirectoryServices.SearchScope]::SubTree
$searchResults = $directorySearcher.FindAll()
#$searchResults
$searchResults.Item(0).Path
If I uncomment #$searchResults then I can see hundreds of entries with "Path" and "Properties" as the objects' properties.
However when $searchResults.Item(0).Path is executed, it just says "Running script/selection. Press ctrl+break to stop." and has been like that for 10 mins so far.
Why can't I access an individual object from the SearchResultCollection ?
Turns out there were just way too many results.
I used a filter to narrow it down and now I can access individual objects since there are now only 347 results.
Before I couldn't even find out the count because there were too many.