Jump to content
MuffinMan

Any other method besides Shell.Windows for creating _IEAttach browser object?

Recommended Posts

MuffinMan

I have been working on an script for work now for quite some time and I finally worked through all my bugs and have the script working great on my desktop.  My ultimate goal however is to run this script on top of another web app as part of a Citrix published app.  However it looks like _IEAttach doesn't want to recognize any browser instances when ran as a published app in Citrix.  It runs fine if I login to Citrix and run it from a desktop.  I found this old thread, but it looks like it was never resolved.

'?do=embed' frameborder='0' data-embedContent>>

I have requested authorization to load AutoIT and sciTE on the Citrix server, but I have not heard back from the admin yet.  I do have a folder on the Citrix server where I can copy my EXEs to for testing.  I'm using straight AutoIT help examples below to show the issues I am seeing so that they will be easy to recreate.

When I compile the WinList HelpFile Example and run it from the Citrix server it sees my browser instances as windows:

#include <MsgBoxConstants.au3>

Example()

Func Example()
    ; Retrieve a list of window handles.
    Local $aList = WinList()

    ; Loop through the array displaying only visable windows with a title.
    For $i = 1 To $aList[0][0]
        If $aList[$i][0] <> "" And BitAND(WinGetState($aList[$i][1]), 2) Then
            MsgBox($MB_SYSTEMMODAL, "", "Title: " & $aList[$i][0] & @CRLF & "Handle: " & $aList[$i][1])
        EndIf
    Next
EndFunc   ;==>Example

But when I compile and run one of the HelpFile _IEAttach examples (below) and run it from the Citrix server, it immediately errors out with:

Line 201 (File "M:StickyNotesIEInstance.exe" ):

Error: Variable must be of type "Object".

#include <IE.au3>
#include <MsgBoxConstants.au3>

Local $aIE[1]
$aIE[0] = 0

Local $i = 1, $oIE
While 1
    $oIE = _IEAttach("", "instance", $i)
    If @error = $_IEStatus_NoMatch Then ExitLoop
    ReDim $aIE[$i + 1]
    $aIE[$i] = $oIE
    $aIE[0] = $i
    $i += 1
WEnd

MsgBox($MB_SYSTEMMODAL, "Browsers Found", "Number of browser instances in the array: " & $aIE[0])

I am really so close on this and I would really appreciate any help you guys could spare.

Edited by MuffinMan

Share this post


Link to post
Share on other sites
JLogan3o13

Can you please clarify your methodology? You want to run the IE instance as a published app, and use an AutoIt script to do an IEAttach from the client desktop - is that correct?

Depending on how the app is being published, this may be problematic at best. Whether you're doing it through Citrix or VMWare, the whole point of publishing applications is encapsulation. If your script sits outside the virtualization "bubble" it is going to be nigh impossible to attach to it.

If you're talking about embedding both AutoIt and IE into the published app, however, that is another matter.

  • Like 1

√-1 2^3 ∑ π, and it was delicious!

Share this post


Link to post
Share on other sites
MuffinMan

Thanks for the quick response, I'll be glad to clarify.  I have done this before with another script I created, but that script did not have to attach to or interact with IE.  the published app is a batch file that runs the script, runs the webapp in IE and then waits for IE to close to kill the script, like this...

start M:StickyNotesmyscript.exe
 
"M:Program Files (x86)Internet Exploreriexplore.exe" http://3rdpartyURL

tskill myscript /a

I have tried starting the webapp from the script via _IECreate, which works, but the _IEAttach still kills the script.  The 3rd party app has multiple nested frames that i have to traverse to get at the data I need.  The script works fine from my desktop, works fine from the Citrix server desktop,, but always fails when ran as a published app.

When I compile and run the WinList example, I see all the browsers as windows, so I would think my script is running in the same bubble, right?

Please let me know if you have any other questions or ideas.

Edited by MuffinMan

Share this post


Link to post
Share on other sites
MuffinMan

So I have continued to work this issue and I still haven't figured out why _IEAttach bombs when running as a Citrix published app. I combined the WinList example with the _IEAttach example to try and attach based on the hwnd, but that didn't work either

Sleep(6000) ; make sure all Citrix browser windows have loaded
Local $aList = WinList()
    ; Loop through the array displaying only visable windows with a title.
    For $i = 1 To $aList[0][0]
        If $aList[$i][0] <> "" And BitAND(WinGetState($aList[$i][1]), 2) AND StringLeft($aList[$i][0],15) = "1st15CharsofWin" Then
            MsgBox(0,"Found Window",$aList[$i][0])
            $oIE = _IEAttach($aList[$i][1], "hwnd")
        EndIf
    Next
MsgBox(0,"","Script Finished")

I get the "Found Window" MsgBox, and then I get same error as in my original script

S8qV7SY.png

I know not everyone here has access to Citrix, but any help or other possibilities would be greatly appreciated.

Share this post


Link to post
Share on other sites
MuffinMan

I have been researching this further and finally found an old thread that mentioned you could run the sciTE executable itself without an install so I thought I would give it a try, using the code I posted above.  This is what I got from the output window just running the .au3 file:

>Running AU3Check (3.3.12.0)  from:\\connect4\c$\Program Files\AutoIt3  input:M:\StickyNotes\winlist.au3
+>15:42:30 AU3Check ended.rc:0
>Running:(3.3.12.0):\\connect4\c$\Program Files\AutoIt3\autoit3_x64.exe "M:\StickyNotes\winlist.au3"    
--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
"\\connect4\c$\Program Files\AutoIt3\Include\IE.au3" (381) : ==> Variable must be of type "Object".:
For $o_window In $o_ShellWindows
For $o_window In $o_ShellWindows^ ERROR
->15:42:39 AutoIt3.exe ended.rc:1
+>15:42:39 AutoIt3Wrapper Finished.
>Exit code: 1    Time: 10.32

So does that mean that for some reason AutoIt isn't recognizing those Citrix published IE windows as true browsers?  This is getting way over my head quickly, but I am willing to do whatever it takes to get this working.  If you have any suggestions or can point me in any direction to troubleshoot this further I would be truly thankful.

Share this post


Link to post
Share on other sites
MuffinMan

OK, another day and another thread bump with my findings.  I added a bunch of MsgBox break points into IE.au3 and I have determined the error I am getting is acually an error with ObjCreate("shell.application") and the ".windows" function that gets the collection of open shell windows.  I will attempt to update the title of the thread (not sure if I can) to reflect this and possibly get some additional help.

This ObjCreate example script (below) works just fine, unless it is ran as a Citrix published app and then it fails...

; Counting the number of open shell windows

Local $oShell = ObjCreate("shell.application") ; Get the Windows Shell Object
Local $oShellWindows = $oShell.windows ; Get the collection of open shell Windows

;If IsObj($oShellWindows) Then <--- REMing out the Object check to force the error
    Local $sString = "" ; String for displaying purposes

    For $oWnd In $oShellWindows ; Count all existing shell windows <---This where the hard error occurs
        $sString &= $oWnd.LocationName & @CRLF
    Next

    MsgBox(0, "", "Shell Windows:" & @CRLF & "You have the following shell windows:" & @CRLF & @CRLF & $sString)
;EndIf

So this seems to be some sort of COM issue, which I know nothing about.  Some more Googling revealed this about Published Apps in Citrix:

From: http://support.citrix.com/article/CTX138775

Seamless Published applications differ from regular published applications by appearing as if it is running directly on the local device and not in a windowed session as in the case with a fixed window published application or in a published desktop. Another difference is, the Windows Desktop/Shell is not present in a Seamless session.

i have a call in to our Citrix admin to see if there is a "non-seamless" published option, but I'm guessing not.  I still don't understand why Winlist always sees the running Citrix windows, but the shell functions do not.  Does anyone know of a way I could edit the IE3.au3 to use another method of attaching to IE or perhaps bypass the browser check altogether?  I don't have the programming prowess to do it, but I do know the window I am attaching to is a browser window because it's the only window I am allowing to be opened by Citrix.

This thread hasn't received much love, and I know no one here owes me a darned thing, but if there's any information I am leaving out or something I need to add in order for this to make more sense please let me know.  I am really desperate to get this working.

Share this post


Link to post
Share on other sites
MuffinMan

I'm bumping this thread again, I've tried every trick I know and still can't get my script to attach to IE when I run the script from the Citrix server as a published app.  Out of desperation, I downloaded a 30 day trial of WinAutomation.  Surprisingly enough, whatever method they use to attach to an IE session also works when ran in Citrix.  Unfortunately, their fill-in-the-blank programming system seems a little clunky and inflexible; I would MUCH rather use AutoIt.

I'm going to update the thread title once again (or should I begin a new thread?) because I guess my real question now becomes is there any other method of creating the object that _IEAttach uses that doesn't involve Shell.Windows?

Share this post


Link to post
Share on other sites
ptroy

Hi!

 

I had the same problem (and was pretty much ready to give up - actually it was worse than that).  But I tried another approach.  Let me explain what I am trying to do, and what I found that seems to work.

- I wanted to close all existing open internet explorer windows

; Close all open internet explorer windows
sleep(1000)
Local $IEWindowList = WinList()
;_ArrayDisplay($IEWindowList)
Local $WindowCounter = $IEWindowList[0][0]
While $WindowCounter >= 0
   If 0 <> StringInStr($IEWindowList[$WindowCounter][0], "Internet Explorer") Then
      ConsoleWrite("*** Closing Internet Explorer Applications using WinList approach - " & $IEWindowList[$WindowCounter][0] & @CRLF)
      WinKill($IEWindowList[$WindowCounter][1])
   Endif
   $WindowCounter = $WindowCounter - 1
WEnd

- I wanted to use _IEAttach but got the same error that you got (while using citrix iwth autoit installed in portable mode);
  I looked at the line in IE.au3 and found the same problem that you found

- I am guessing that the com object reference created by ObjCreate is the same reference returned by _IEAttach;  I am hoping to verify that soon.  So, I decided to directly create an InternetExplorer.Application com object.  Note that it does not always suceed the first time so I have it in a loop until it does succeed.

; Try to create internet explorer automation object (which I believe to also be a com object)
; - It doesn't always succeed the first time so I repeat until it succeeds
sleep(1000)
Local $IEWindowComObject = ObjCreate("InternetExplorer.Application")
while @error <> 0
   ConsoleWrite("*** Just attempted to create internet explorer com object " & @error & @CRLF)
   sleep(1000)
   $IEWindowComObject = ObjCreate("InternetExplorer.Application")
WEnd

; Make it visible and go to ipad and then wait until the window is read
$IEWindowComObject.Visible = true;
$IEWindowComObject.navigate("https://www.google.ca")
If @error then
   $IEWindowComObject.Quit
   Return
EndIf
While 1
   If $IEWindowComObject.readyState = "complete" or $IEWindowComObject.readyState = 4 then ExitLoop
   sleep(1000)
WEnd

- I needed the title to determine the state the window is open; in my case there are actually two possibilities

; Get window handle, needed to get the title, of new internet explorer window
$IEWindowList = WinList()
;_ArrayDisplay($IEWindowList)
$WindowCounter = $IEWindowList[0][0]
Local $IEWindowHandle = 0
While $WindowCounter >= 0 AND $IEWindowHandle = 0
   If 0 <> StringInStr($IEWindowList[$WindowCounter][0], "Internet Explorer") Then
      ConsoleWrite("*** Found Internet Explorer window - " & $IEWindowList[$WindowCounter][0] & @CRLF)
      $IEWindowHandle = $IEWindowList[$WindowCounter][1]
   Endif
   $WindowCounter = $WindowCounter - 1
WEnd

; Get window title
Local $IEWindowTitle = ""
IF $IEWindowHandle <> 0 Then
   $IEWindowTitle = WinGetTitle($IEWindowHandle)
EndIf
;_ArrayDisplay($IEWindowList)
sleep(5000)
ConsoleWrite($IEWindowTitle & @CRLF)

- As I mentioned before, I think that $IEWindowComObject is the value that should have been returned by _IEAttach if it worked.

If I am correct about this, that the com object reference is the reference returned by _IEAttach when it works, it would be extremely helpful if the documentation was modified to indicate this.

All the best . . .

Phil Troy

Edited by JLogan3o13
Added Code Formatting
  • Like 1

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

  • Similar Content

    • MakzNovice
      By MakzNovice
      Hello Experts,
      I am working on modifying table data of a browser currently in IE (soon in FF)
      My sequence of operations:
      1. Activate Browser
      2. Get Browser table
      3. Modify data  in table
      4. Suppress any warning/error message from webpage
      5. Activate the Webpage again 
      6. Send {F11} key sequence twice to achieve some update without Updating form ( {F5})
       
      My problem is at Step 5, as it activates the wrong window ( last used application rather than my browser window)
      My code snippet for it as follows
      $bFoundWindow = False Local $aList = WinList("[REGEXPTITLE:(?i)(.*Internet Explorer.*)]") Local $hWND = 0 For $i = 1 To $aList[0][0] If False = $bFoundWindow And $aList[$i][0] <> "" And BitAND(WinGetState($aList[$i][1]), 1) Then WinActivate($aList[$i][1]) ; 1. Activate Browser window WinSetState ( $aList[$i][1], "", @SW_MAXIMIZE) $hWND = $aList[$i][1] $objEditIE = _IEAttach ($aList[$i][1], "hwnd") $oTitles = _IETagNameGetCollection($objEditIE, "TITLE") For $oTitle In $oTitles $sTitle = $oTitle.innerText If $sTitle = $searchString Then MsgBox(0,"APPLICATION Found", "Got Edit List Window", 1) $bFoundWindow = True ExitLoop EndIf Next EndIf Next If False = $bFoundWindow Then MsgBox(0,"Error","Please launch Edit window for updating values in Browser prior to script execution",10) Exit EndIf ; MY CODE HERE TO MODIFY TABLE ; 2. Get Browser table ; 3. Modify data  in table ; Check if message from webpage pop-up window exists if so click ok on it Local $nCounter = 0 Local $nMaxCounter = 5 while 1 If WinExists("Message from webpage","") Then ControlClick("Message from webpage","","Button1","primary",1) ;4. Suppress any warning/error message from webpage Else $nCounter = $nCounter + 1 Sleep(100) ;MsgBox(0,"Counter", $nCounter, 1) If $nCounter = $nMaxCounter Then ExitLoop EndIf WEnd ;5. Activate the Webpage again  WinActivate($hWND) ; have already tried WinActivate($aList[$i][1]) but no success ;6. Send {F11} key sequence twice to achieve some update without Updating form ( {F5}) Send("{F11}") WinActivate($hWND) ;WinActivate($aList[$i][1]) Sleep(100) Send("{F11}") Any support will be highly appreciated
    • MakzNovice
      By MakzNovice
      Hello Experts,
      I am working on custom application details of which I am unable to share.
      But here is statement of my problem, I have two IE windows one window with Title "Parent " and other with "TableEdit", but for some reason when I get WinList they are shown as 2 processes each. ( see attached image)
      Since my most important motive is to modify table data in 'TableEdit' I try to access the table in it
      My code snippet is 
      ***********************************************************************************************
      $searchString = "TableEdit"
      Local $aList = WinList("[REGEXPTITLE:(?i)(.*Internet Explorer.*)]")
      _ArrayDisplay($aList)
      For $i = 1 To $aList[0][0]
          If $aList[$i][0] <> "" And BitAND(WinGetState($aList[$i][1]), 2) Then
              ;MsgBox($MB_SYSTEMMODAL, "", "Title: " & $aList[$i][0] & @CRLF & "Handle: " & $aList[$i][1])
              If 0 <> StringInStr($aList[$i][0],"TableEdit") Then
                  $objEditIE = _IEAttach ($aList[$i][1])
                  ExitLoop
              EndIf
          EndIf
      Next
      WinActivate($objEditIE)
      $oPageContentListFrame = _IEFrameGetObjByName($objEditIE, "iframe_1")
      $iNumFrames = @extended
      MsgBox(0,"Got pagecontent",@error) ; returns 3, indicating invalid data type
      MsgBox(0,"Number of Frame",$iNumFrames) ; returns 1, expected value is 1 
      ***********************************************************************************************
      and If I do code as below the return value is different
      $searchString = "TableEdit"
       $objEditIE = _IEAttach ($searchString, "title")
      WinActivate($objEditIE)
      $oPageContentListFrame = _IEFrameGetObjByName($objEditIE, "iframe_1")
      $iNumFrames = @extended
      MsgBox(0,"Got pagecontent",@error) ; returns 0
      MsgBox(0,"Number of Frame",$iNumFrames) ; returns 0. expected value is 1
      ***********************************************************************************************
      What is wrong with my code? 
      Why do I see two process each for IE for each window?
       
      WinListImage.bmp
    • fenhanxue
      By fenhanxue
      I have a folder A   (  C:\FolderA  ),  It contains many files :
      C:\FolderA\1.jpg
      C:\FolderA\2.jpg
      C:\FolderA\3.jpg
      ...
      I want to copy the folder A to the folder B   (  C:\FolderB  ) like follow :
      C:\FolderB\1.jpg
      C:\FolderB\2.jpg
      C:\FolderB\3.jpg
      ...
       
      I do not want to use  'DirCopy',although this code can  help me achieve my request:
      $SourceDir = 'C:\FolderA' $Destdir = 'C:\FolderB' DirCopy($SourceDir,$Destdir,1)  
      I want to use 'Shell.Application ' instand  ,so this is my code as follow:
      $SourceDir = 'C:\FolderA' $Destdir = 'C:\FolderB' $Shell = ObjCreate("Shell.Application") $Shell.NameSpace($Destdir).MoveHere($SourceDir, 16)  
      My problem is :
      when i use 'Shell.Application '  ,  The folder B turns this way:
      C:\FolderB\FolderA\1.jpg
      C:\FolderB\FolderA\2.jpg
      C:\FolderB\FolderA\3.jpg
      ...
       
      what i need is:
      C:\FolderB\1.jpg  
      C:\FolderB\2.jpg 
      C:\FolderB\3.jpg 
      ...
      so can you help me ?
    • Tippex
      By Tippex
      I have a problem trying to use _IEAttach to recover control after a Windows Explorer reset (e.g. on Windows 7), since all the 
      InternetExplorer.Application objects appear to be destroyed by this event. An example of this is when a PC has some kind of fault causing a pop-up error message "Windows Explorer has stopped working". I can simulate this event by using Windows Task Manager to end the Explorer.exe process then to file, new task (run...) Explorer.exe
      After this event, _IEAttach gives an @error of: 
      7 ($_IEStatus_NoMatch) - No Match
      However, using WinList() followed by WinGetText() I can recover the URL for an IE session that has lost its 
      InternetExplorer.Application object which could be used to _IECreate a new session (the $iTryAttach fails) and WinKill() the original session but the result is a if a refresh had been done (any form entries are lost) . Unfortunately form entries do not appear as text or hidden text to Windows so I'm looking for the best way to read the contents of an Internet Explorer screen (even if just text without structure). 
      When there is no InternetExplorer.Application object (because of some Windows fault) but still with an Internet Explorer session running, I tried to read its contents by a "Select All" & "Copy to Clipboard" but its form entries are blanked and combo boxes choices are all displayed with no way of finding out which ones were selected.
      Local $ClipBoardSave = _ClipBoard_GetData() ;not ClipGet() which is text only ClipPut("") ;Clear User's Clipboard Local $sText = "" Local $hWnd = WinActivate("Window Title", "") If IsHWnd($hWnd) Then Local $bStatusCtrlSend = ControlSend("Window Title", "", "", "^a^c") If $bStatusCtrlSend Then Local $bStatusCtrlClick = ControlClick("Window Title", "", "") If $bStatusCtrlClick Then $sText = ClipGet() _ClipBoard_SetData($ClipBoardSave) ;not ClipPut($ClipBoardSave) which is text only  
      Is  there a solution to this please?
    • Tippex
      By Tippex
      I'm having a problem with _IEBodyReadText() which is a function from the IE.au3 UDF include.
      My problem is that randomly it will crash my script with:
      Return SetError($_IESTATUS_Success, 0, $oObject.document.body.innerText) Return SetError($_IESTATUS_Success, 0, $oObject.document.body^ ERROR I don't know why the error isn't caught by __IEErrorHandlerRegister but looking at this function, I can see that there is a check done by IsObj($oObject) to ensure that the object "$oObject" exists but no check that it contains the property "innerText"
      ; #FUNCTION# ==================================================================================================================== ; Author ........: Dale Hohm ; =============================================================================================================================== Func _IEBodyReadText(ByRef $oObject) If Not IsObj($oObject) Then __IEConsoleWriteError("Error", "_IEBodyReadText", "$_IESTATUS_InvalidDataType") Return SetError($_IESTATUS_InvalidDataType, 1, 0) EndIf If Not __IEIsObjType($oObject, "browserdom") Then __IEConsoleWriteError("Error", "_IEBodyReadText", "$_IESTATUS_InvalidObjectType", "Expected document element") Return SetError($_IESTATUS_InvalidObjectType, 1, 0) EndIf ; Return SetError($_IESTATUS_Success, 0, $oObject.document.body.innerText) EndFunc ;==>_IEBodyReadText I'm struggling to find out how to test if "$oObject.document.body.innerText" exists before allowing the following Return statement to reference it with the assumption that it does exist (crashing my script when it doesn't).
      Any ideas please?
×