Sign in to follow this  
Followers 0

IECreate2

41 posts in this topic

Posted (edited)

The _IE*() UDF is awesome, dont get me wrong, I adore them, and use them every day lol. But, sometimes, with some sites, some content, some items, it is not possible to actually use an embedded IE to accomplish the mission that you want. For example, creating dynamic IFrames and DIV's within IFRAMES, or accessing local sites through a connected local DNS VPN (it's rather complex lol).

So, i needed a way to get around that. It's great that IE has a -k function (-k = kiosk mode). Using this method, you can actually create a method for usage. Here's an example

#Include <WindowsConstants.au3>
#include <WinAPI.au3>
#Include <Constants.au3>
local $pid, $hHandle, $hGUI, $sURL, $xHeight, $xWidth
$sURL = "www.google.com"
$xWidth = 1024
$xHeight = 768
$hGUI = GUICreate("Test", $xWidth, $xHeight)
_IECreate2($xWidth, $xHeight, $hGUI)

func _IECreate2($xWidth, $xHeight, $hGUI)
$pid = Run(@ProgramFilesDir&"\internet explorer\iexplore.exe -k "&$sURL, "", @SW_HIDE)
Sleep(2000)
$hHandle = _ProcessGetHWnd($pid)
GUISetState(@SW_SHOW, $hGUI)
_WinAPI_SetParent($hHandle, $hGUI)
_WinAPI_MoveWindow($hHandle, 0, 0, 1024, 768, True)
_WinAPI_SetWindowLong($hHandle, $GWL_STYLE, $WS_POPUP+$WS_VISIBLE)
Send("{F5}")
EndFunc
Func _ProcessGetHWnd($iPid, $iOption = 1, $sTitle = "", $iTimeout = 2000)
    Local $aReturn[1][1] = [[0]], $aWin, $hTimer = TimerInit()
    While 1
      $aWin = WinList($sTitle)
        For $i = 1 To $aWin[0][0]
            If $iPid = WinGetProcess($aWin[$i][1]) Then
                If $iOption = 1 OR ($iOption = 0 And $aWin[$i][0] <> "") Then
                    Return $aWin[$i][1]
                ElseIf $iOption = 2 Then
                    ReDim $aReturn[UBound($aReturn) + 1][2]
                    $aReturn[0][0] += 1
                    $aReturn[$aReturn[0][0]][0] = $aWin[$i][0]
                    $aReturn[$aReturn[0][0]][1] = $aWin[$i][1]
                EndIf
            EndIf
        Next
        If $iOption = 2 And $aReturn[0][0] > 0 Then Return $aReturn
        If TimerDiff($hTimer) > $iTimeout Then ExitLoop
        Sleep(Opt("WinWaitDelay"))
    WEnd
       SetError(1)
    Return 0
EndFunc  ;==>_ProcessGetHWnd

Do
    Sleep(200)
Until GUIGetMsg() = -3
ProcessClose($pid)

You can replace the SEND() function with some _IE*() commands to attach to the embeded IE control and initiate a redraw/repait/refresh, but the SEND is quicker, imho.

What it does:

* Creates a full IE instance

* Embeds the IE instance to a GUI window

* Stops flickering on display by not showing the GUI window until the the IE is created.

Hope it's of use >_<

Just thought i'd post.

Edited by zackrspv
header127 likes this

Share this post


Link to post
Share on other sites



Posted

Nice post >_< helped me allot with a project I'm starting.

Share this post


Link to post
Share on other sites

Posted

Sweet action! Exactly what I needed!

Share this post


Link to post
Share on other sites

Posted

Hi Zack

I'm new to IE UDF, but see, in the example that follows, it can't distinguish if I'm connected or not to Internet.

#include <IE.au3>
_IELoadWaitTimeout (10000)
$oIE = _IECreate ('sourceforge.net' ,0,1,0)
_IELoadWait($oIE,100,100)
$x=AT error
$y=$oIE
MsgBox(4096,1, hex($y) & AT crlf & $x)

_IEQuit ($oIE)
so:

1- if I'm connected AND _IELoadWait($oIE,100,100) ==> @error returns 6, as expected as 100ms is a very low timeout

2- if i'm NOT connected and _IELoadWait($oIE,100,100) ==> @error returns 0!!!

3- if timeout is resonable (10.000), no matter if I'm conected or NOT, @error returns ALWAYS 0!!!

---> So, how can I detect if I'm connected or not? Seems to me that in the NOT connected state I shoud not receive @error=0, it shoud be 6 or any other thing.

Do you have a clue on how can I detect if I'm connected or not?

Thanks

Jose

p.s. sorry for the AT, but I can't devise how to deal with this new very slow forum rules, the symbol for AT makes it to create an email...

Share this post


Link to post
Share on other sites

Posted

This techniques seems to work quite well and I have been recommending it to anyone who has trouble with _IECreateEmbedded. This technique uses a full browser instance instead of the limited webbrowser control and the AutoIt GUI activeX container.

I would like to see a cleaner approach to the _ProcessGetHWnd routine however...

Dale

Share this post


Link to post
Share on other sites

Posted

This techniques seems to work quite well and I have been recommending it to anyone who has trouble with _IECreateEmbedded. This technique uses a full browser instance instead of the limited webbrowser control and the AutoIt GUI activeX container.

I would like to see a cleaner approach to the _ProcessGetHWnd routine however...

Dale

perfect! it works!

thx

Share this post


Link to post
Share on other sites

Posted (edited)

Watch out with IE8 and the new multiprocess model. It leaves orphaned iexplore.exe processes.

Edited by wraithdu

Share this post


Link to post
Share on other sites

Posted

adding a check for child processes at your _disconnect() routine (calling before you exit, or on exit) can remove the child IExplore.exe's

Share this post


Link to post
Share on other sites

Posted

Hi all,

So is this the only way I'm going to be able to open intranet sites that require domain login?

That's kind of my only problem right now with embedded internet explorer:

I can't open any site that requires "internal" authentication (the little Internet Explorer pop-up that opens for instance when you access most routers).

The script provided in the first post isn't very 'accurate', I might say, because there's a certain timeout event before I'm able to provide the login details and allow AutoIt to "grab" the Internet Explorer instance into its window.

The point would be letting the user enter appropriate login credentials manually (or do you know an automated way of performing that kind of login?).

Any ideas?

Thank you in advance.

footswitch

Share this post


Link to post
Share on other sites

Posted

The script provided in the first post isn't very 'accurate', I might say, because there's a certain timeout event before I'm able to provide the login details and allow AutoIt to "grab" the Internet Explorer instance into its window.

It's not a matter of accuracy, it was a method of showing you an alternative to useing a Shell.2 for embeded objects.

In your case, you could simply just wait for the box to come up, and if the WinExist() check passes, send the proper keystrokes to the window. That's what I did when i had to log into my VPN automatically.

Just open it in a normal IE browser, run the Au3Info tool, and pull the window title/information out of it,a nd field names out, and wait for them to appear, then send your information to the window, and send the enter keystroke to finish it off. Then just wait. the IE() functions work just fine w/ this.

Share this post


Link to post
Share on other sites

Posted

It's not a matter of accuracy, it was a method of showing you an alternative to useing a Shell.2 for embeded objects.

In your case, you could simply just wait for the box to come up, and if the WinExist() check passes, send the proper keystrokes to the window. That's what I did when i had to log into my VPN automatically.

Just open it in a normal IE browser, run the Au3Info tool, and pull the window title/information out of it,a nd field names out, and wait for them to appear, then send your information to the window, and send the enter keystroke to finish it off. Then just wait. the IE() functions work just fine w/ this.

Thank you for your reply, zack.

Nevertheless, allow me to further ellaborate:

When using _IECreateEmbedded, the login box doesn't appear at all.

That's my exact problem. When using a regular IE window (_IECreate), the box appears and allows either manual or automated login. But with the embedded option, the navigation just fails without prompting for authentication (if I open www.google.com, it works, but if I open a site that requires that kind of authentication, it doesn't work).

Your method seems to provide a solution; however, as forementioned, it's not as "stable" as _IECreateEmbedded or _IECreate.

But I must say I don't quite understand all the scripting in your example (i.e. why it is needed to work).

In my case, depending on the workstation, whether it's part of the domain or not, or if it has logged in to it previously, that login box could or could not appear (in some workstations the login box appears, and in others it doesn't - it opens the site right away, even in embedded mode).

footswitch

Share this post


Link to post
Share on other sites

Posted (edited)

Thank you for your reply, zack.

Nevertheless, allow me to further ellaborate:

When using _IECreateEmbedded, the login box doesn't appear at all.

That's my exact problem. When using a regular IE window (_IECreate), the box appears and allows either manual or automated login. But with the embedded option, the navigation just fails without prompting for authentication (if I open www.google.com, it works, but if I open a site that requires that kind of authentication, it doesn't work).

Your method seems to provide a solution; however, as forementioned, it's not as "stable" as _IECreateEmbedded or _IECreate.

But I must say I don't quite understand all the scripting in your example (i.e. why it is needed to work).

In my case, depending on the workstation, whether it's part of the domain or not, or if it has logged in to it previously, that login box could or could not appear (in some workstations the login box appears, and in others it doesn't - it opens the site right away, even in embedded mode).

footswitch

hello there.

The method i use is very simnilar to how IECreate works, it just uses a kiosk mode IE instance, instead of the normal ie window. So the IE commands still work on it w/o issue. The whole process i would recommend you use, however, is the following:

1. Create the _IECreate2() instance

2. Navigate to your VPN Page

3. Use the IELoadWait() or the IEBussy*() commands to ensure the page is loaded

4. Do a if exist check. Ie, check if the login window is up

5. If not, continue on.

6. If so, send the login information.

That would prevent your systems from having to rely on LDAP checks to see if the AD login information is already passed.

In instances where you are creating VPN connections, you have to see if they are previously logged in. You could always check for an LDAP authentication token on the system, but that is awefully complex to do. Secondly, you could just do what is above, and see if the steps to connect, can solve the issue for you.

If you need help understanding what i did in the first post, and why it's formatted the way it is, please ask ;) More than willing to share why it is the way it is :evil:

Edited by zackrspv

Share this post


Link to post
Share on other sites

Posted

So here we are again! Posted Image

I didn't give up on your solution, and here's what I came up with.

A simple way of "always" grabbing the IE window is to start it with a page that will always load: about:blank

I cut off some stuff from your original script. The only thing that I think it's missing is a timer that would allow the application to return an error or try again.

This is my version:

#Include <WindowsConstants.au3>
#include <WinAPI.au3>
#Include <Constants.au3>
#include <IE.au3>

local $pid, $hHandle, $hGUI, $sURL, $xHeight, $xWidth
$sURL = "about:blank"
$xWidth = 800
$xHeight = 600
$hGUI = GUICreate("Test", $xWidth, $xHeight)
$oIE=_IECreate2($xWidth, $xHeight, $hGUI)
_IENavigate($oIE,"www.google.com")

Func _IECreate2($xWidth, $xHeight, $hGUI)
$pid = Run(@ProgramFilesDir&"\internet explorer\iexplore.exe -k "&$sURL, "", @SW_HIDE)
Sleep(1000)
$hHandle = _ProcessGetHWnd($pid)
Do
$oIElocal=_IEAttach($hHandle,"HWND")
Sleep(500) ; add a timer here
Until $oIElocal<>0
GUISetState(@SW_SHOW, $hGUI)
_WinAPI_SetParent($hHandle, $hGUI)
_WinAPI_MoveWindow($hHandle, $xWidth-256, 0, 256, $xHeight-128, True)
_WinAPI_SetWindowLong($hHandle, $GWL_STYLE, $WS_POPUP+$WS_VISIBLE)
Return $oIElocal
EndFunc


Func _ProcessGetHWnd($iPid, $sTitle = "", $iTimeout = 2000)
Local $aWin
    While 1
    $aWin = WinList($sTitle)
        For $i = 1 To $aWin[0][0]
            If $iPid = WinGetProcess($aWin[$i][1]) Then
    Return $aWin[$i][1]
   EndIf
  Next
  Sleep(500) ; add a timer here
    WEnd
    SetError(1)
    Return 0
EndFunc

Do
    Sleep(200)
Until GUIGetMsg() = -3
ProcessClose($pid)

And as far as I've tested, this works for me Posted Image so THANK YOU Posted Image

I just have this minor question... How do I add a frame (border) around the IE window, so that the user will clearly see the IE limit box inside the GUI?

I tried some Window Style constants ($WS_*), to no avail.

Oh and the IE8 thing... It really leaves some orphan processes when it's closed. Is there a simple way of cleaning the remaining processes without taking the risk of closing the wrong IE windows?

Could you help me figure out what I'm missing this time? Posted Image

Again thank you for your time.

Regards,

footswitch

Share this post


Link to post
Share on other sites

Posted

Oh and the IE8 thing... It really leaves some orphan processes when it's closed. Is there a simple way of cleaning the remaining processes without taking the risk of closing the wrong IE windows?

Did you try _IEQuit() ?

Dale

Share this post


Link to post
Share on other sites

Posted

Did you try _IEQuit() ?

Dale

Lol. I might as well try that :)

And about the frame (border) around the IE Object, it just occurred to me that I could draw a line around it.

Some things are indeed better with the simplest approach!

Thanks :idea:

footswitch

Share this post


Link to post
Share on other sites

Posted

Lol. I might as well try that :)

And about the frame (border) around the IE Object, it just occurred to me that I could draw a line around it.

Some things are indeed better with the simplest approach!

Thanks :idea:

footswitch

Hello again,

Just reporting my results.

The _IEQuit() works perfectly. Thanks!

For the frame around the object I used this:

GUICtrlCreateLabel ("", $a, $b, $c, $d,$SS_SUNKEN)

All the best,

footswitch

Share this post


Link to post
Share on other sites

Posted

I love this! Thanks!

Share this post


Link to post
Share on other sites

Posted

What if i wanted to position the window specifically inside the GUI...?

Share this post


Link to post
Share on other sites

Posted (edited)

My version, added positioning, sizing, and a few tweaks.

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <Constants.au3>
#include <IE.au3>

Local $pid, $hHandle, $hGUI, $sURL, $xHeight, $xWidth
$sURL = "about:blank"
$xWidth = 800
$xHeight = 600
$hGUI = GUICreate("Test", $xWidth, $xHeight)
$oIE = _IECreateEmbed2(500, 500, 10, 10, $hGUI)
_IENavigate($oIE, "www.google.com")

Func _IECreateEmbed2($xWidth, $xHeight, $iX, $iY, $hGUI)
    $pID = Run(@ProgramFilesDir & "\internet explorer\iexplore.exe -k " & $sURL, "", @SW_HIDE)
    Do
        Sleep(100)
    Until Not (ProcessExists($pID) = 0)
    $hHandle = _ProcessGetHWnd($pID)
    Do
        $oIElocal = _IEAttach($hHandle, "HWND")
        Sleep(100)
    Until $oIElocal <> 0
    GUISetState(@SW_SHOW, $hGUI)
    _WinAPI_SetParent($hHandle, $hGUI)
    _WinAPI_MoveWindow($hHandle, $iX, $iY, $xWidth, $xHeight, True)
    _WinAPI_SetWindowLong($hHandle, $GWL_STYLE, BitOR($WS_CHILD, $WS_VISIBLE))
    Return $oIElocal
EndFunc   ;==>_IECreate2

Func _ProcessGetHWnd($iPid, $sTitle = "", $iTimeout = 2000)
    Local $aWin
    While 1
        $aWin = WinList($sTitle)
        For $i = 1 To $aWin[0][0]
            If $iPid = WinGetProcess($aWin[$i][1]) Then
                Return $aWin[$i][1]
            EndIf
        Next
        Sleep(500) ; add a timer here
    WEnd
    SetError(1)
    Return 0
EndFunc   ;==>_ProcessGetHWnd

Do
    Sleep(50)
Until GUIGetMsg() = $GUI_EVENT_CLOSE
_IEQuit($oIE)
Edited by motionman95

Share this post


Link to post
Share on other sites

Posted

This is pretty good, one thing is that they create multiple instances of iexplore.exe

@ motionman95 you example creates 2 instances, and only closes 1, could still hear the youtube video going on after the gui was closed and 1 instance was closed.

Its ok to work around, but would be much better if it didnt happen

Other than that pretty nice.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0