2014-03-19 15 views
5

Ich schreibe derzeit ein Skript und ich bin mitKann Powershell warten, bis IE DOM bereit ist?

while($IE.busy) {Start-Sleep 1} 

zu warten, die Seite bereit zu sein.

Sobald die Seite fertig ist, füllt sich mein Skript aus und sendet ein Formular. Ich habe Probleme bekommen, weil (ich denke) IE berichtet, dass es gemacht wird, wenn die Seite geladen wird, aber bevor das Dokument gerendert wurde (was das Skript zu einem Fehler führt). Meine aktuelle Problemumgehung besteht darin, nach dem Laden der Seite eine Wartezeit von 4 Sekunden hinzuzufügen, aber ich würde mich mit einer Methode, die möglichst nicht zeitbasiert ist, wohler fühlen.

+1

ich Dich mit dem 'InternetExlporer.Application' COM-Objekt zu übernehmen werde? Wenn dies der Fall ist, können Sie wahrscheinlich keine Ereignisse abonnieren, da es kein .NET-Objekt ist. Wenn es ein .NET-Objekt wäre, könnten Sie 'Register-ObjectEvent' verwenden, um einen Event-Handler zu verbinden. –

+0

Richtig, ich benutze das IE COM-Objekt. Also denke ich, die Wartezeit auf eine Zeit zu erhöhen, von der ich denke, dass sie sicher ist, ist die einzige Option? –

+1

Soweit ich weiß, ist die zeitbasierte Überprüfung die beste Wahl.Wenn Sie nach einer bestimmten Zeit (z. B. 5 Minuten) nicht mehr überprüfen möchten, können Sie eine 'break'-Anweisung innerhalb der 'while'-Schleife verwenden. –

Antwort

2

So mache ich das.

Schritt 1 - Identifizieren Sie ein Webseitenelement, das erst erscheint, wenn die Seite vollständig gerendert wurde. Ich habe dies mit der Ansicht "Elemente" der Chrome-Entwicklungstools gemacht, die die DOM-Ansicht zeigt.

Schritt 2 - Legen Sie eine Warteschleife im Skript fest, die die Existenz des Elements oder den Wert von Text in diesem Element abfragt.

# Element ID to check for in DOM 
$elementID = "systemmessage" 

# Text to match in elemend 
$elementMatchText = "logged in" 

# Timeout 
$timeoutMilliseconds = 5000 

$ie = New-Object -ComObject "InternetExplorer.Application" 

# optional 
$ie.Visible = $true 

$ie.Navigate2("http://somewebpage") 
$timeStart = Get-Date 
$exitFlag = $false 

do { 

    sleep -milliseconds 100 

    if ($ie.ReadyState -eq 4) { 

     $elementText = (($ie.Document).getElementByID($elementID)).innerText 
     $elementMatch = $elementText -match $elementMatchText 

     if ($elementMatch) { $loadTime = (Get-Date).subtract($timeStart) } 

    } 

    $timeout = ((Get-Date).subtract($timeStart)).TotalMilliseconds -gt $timeoutMilliseconds 
    $exitFlag = $elementMatch -or $timeout 

} until ($exitFlag) 

Write-Host "Match element found: $elementMatch" 
Write-Host "Timeout: $timeout" 
Write-Host "Load Time: $loadTime" 
2

Ich fand diesen Thread wirklich hilfreich und endete mit einer etwas anderen Lösung. Ich bin ziemlich neu in Powershell, also habe ich hoffentlich kein Hash gemacht, aber das hat wirklich gut für mich funktioniert.

ich verwendet, um eine „while“ Aussage so, dass mein Zustand würde Schleife während wahr:

while($ie.document.body.outerHTML -notMatch "<input type=`"submit`" value=`"Continue`">") {start-sleep -m 100}; 

In diesem Fall habe ich gegen einen Teil des „Outerhtml“ Teil des Körpers passend war. Solange ich nicht mit dem angegebenen Text übereinstimme, wartet das Skript und wiederholt die Übereinstimmungsüberprüfung.

Ich mag diese Lösung, da ich es in mehr oder weniger einer Zeile Code tun könnte, und ich mag es, Dinge kompakt zu halten, wo es möglich ist. Hoffentlich ist das hilfreich für jemand anderen. Wie das OP fand ich ie.readystate, um sehr finnicky/unzuverlässig zu sein, aber ich wollte wirklich nicht einfach einen statischen Schlummertimer setzen.

Auch während Chrom ist eine ausgezeichnete Weise, eine Seite zu brechen. Sie können auch in das Konsolenfenster drucken, sobald Sie IE läuft programmgesteuert einfach ausgeführt wird:

$ie.document.body 

Sie durch visuell graben und dann filtern bis auf den Abschnitt, den Sie möchten, welche Ihre passende beschleunigen sollte (ich würde vermuten) , was ich oben in meinem Codebeispiel getan habe.

Die einzige andere Sache, die ich beachten werde ... Ich denke, -match verwendet "regex", weil ich das Häkchen (ex. `) Verwenden musste, um die Anführungszeichen zu umgehen, die Teil der Zeichenfolge waren, die ich passte.

Prost!

Hier ist eine gute Referenz auf „während“ Logik: http://www.powershellpro.com/powershell-tutorial-introduction/logic-using-loops/

Verwandte Themen