views:

839

answers:

1

Hey.
I'm writing powershell script that simulates actions performed by user on the page. I have a problem with performing click on a button. Page has form and inside button that saves changes to database:

input type="button" onClick="__doPostBack('someIdentifier','SAVE')" value="Save changes"

I need to invoke that from the client side. Problem is that button it self has id="" and tag="" so the following doesn't work:

$ie = new-object -com "InternetExplorer.Application";
$ie.visible = $true;
$ie.navigate("http://myTestedPage.com");
$doc = $ie.Document;

#doesn't work
$save = $doc.getElementByID("")
#doesn't work neither
$save = $doc.getElementsByTagName("");

#so how to call
$save.click();

both getElementbyID and getElementsByTagName just perform some operations but only effect they have is my CPU usage jumping to max.

I was thinking about getting elements[] of the form and finding button there but it doesn't neither (effects like in previous case).

Is there some other (brilliant) way to do that (that obviously I'm not aware of)? I would need something like InvokeScript

webBrowser = new System.Windows.Forms.WebBrowser()
webBrowser.Document.InvokeScript(@"__doPostBack", new object[] {@"someIdentifier", @"SAVE"});

but I need to use instance of IE manipulated by powershell (or other scripting/programming language, maybe VBScript?), not .NET standalone app.

+1  A: 

2nd attempt

The following code searches for and clicks on all input elements that have a value="Save changes" attribute.

I had to read the attribute's nodeValue property dynamically since it wasn't exposed in the interface.

function getProperty ([System.__ComObject] $obj, [string] $prop)
{
    [System.__ComObject].InvokeMember($prop, [System.Reflection.BindingFlags]::GetProperty, $null, $obj, $null)
}

$ie = new-object -com "InternetExplorer.Application"
$ie.visible = $true
$ie.navigate('e:\scratch\h.html')
$doc = $ie.Document

$inputElts = $doc.getElementsByTagName('input')
foreach ($elt in $inputElts)
{
    $a = $elt.getAttributeNode('value')
    if ($a -and (getProperty $a 'nodeValue') -eq 'Save changes')
    {
        $elt.Click()
    }
}

This is my HTML:

<html>
<head>
<script type="text/javascript">
function alertMsg() {alert("Button was clicked!")}
</script>
</head>
<body>
<form>
<input type="button" onclick="alertMsg()"  value="Save changes" />
</form>
</body>
</html>
dangph
Well that's the point - both TAG and ID are empty for this button (I've mentioned this in my question). So I can't (or I don't know how) catch button object therefore I'm looking for a way to invoke __dopostback that is executed on button click.
yoosiba
Okay, I didn't see that. You should provide minimal but *complete* code in order to reduce the chance of misunderstanding. Your input element BTW does have a tag. It is "input". Unfortunately the collection returned by getElementsByTagName("input") doesn't have any useful methods or properties ...
dangph
... Strangely, most of the DOM objects from IE in PowerShell have incomplete interfaces. That will make the job harder. I may have another look later.
dangph
Hey. Did that code actually worked for you? First of all should there be getPropety in loop? My PS is throwing errors. If you meant $a.getPropety('nodeValue') this object doesn't contain this method. If it was supposed to be get-member $a 'nodeValue' then this object doesn't contain this property.
yoosiba
Yes of course it worked for me. getProperty is a function I wrote. It is at the top of the code. I needed it access the nodeValue property, as I explained. You can look up nodeValue here: http://msdn.microsoft.com/en-us/library/aa752509(VS.85).aspx . As I said, nodeValue isn't visible. ...
dangph
... that's why I had to use InvokeMember to get it. The reason it is invisible is too complicated to explain here."My PS is throwing errors" is not helpful.
dangph
I dunno why I skipped function at the beginning. Anyway it works great!
yoosiba