Peter Groves
asked on
Code from part a opens a new window after execution is complete. How do I continue with part B if execution is waiting input?
I click a button to load an Excel file from a website via a Export to excel menu choice! The code below works fine and
opens the File download window except the newly opened 'save file to' window only opens
when the code exits the subroutine and wait for a new user input! .
How do I continue executing the second part of code that clicks the save button to actually save the file
as the window doesn't open until the first part finishes executing!
opens the File download window except the newly opened 'save file to' window only opens
when the code exits the subroutine and wait for a new user input! .
How do I continue executing the second part of code that clicks the save button to actually save the file
as the window doesn't open until the first part finishes executing!
Imports System.Runtime.InteropServices
Imports System.Text
Public Class activeWin
Private Sub ActiveWin_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GetActiveWindows()
End Sub
'Public Delegate Function CallBack(ByVal hwnd As Integer, ByVal lParam As Integer) As Boolean
Public Delegate Function CallBack(ByVal hwnd As IntPtr, ByVal lParam As Integer) As Boolean
Public listcount As Integer = 0
Public Declare Function EnumWindows Lib "user32" (ByVal Adress As CallBack, ByVal y As Integer) As Integer
Public Declare Function IsWindowVisible Lib "user32.dll" (ByVal hwnd As IntPtr) As Boolean
Private Const SW_HIDE As Integer = 0
Private Const SW_RESTORE As Integer = 9
Public hwnd As IntPtr
Public selectedIndex As Integer
Public xAsIntPtr, cxAsIntPtr As IntPtr
Private ActiveWindows As New System.Collections.ObjectModel.Collection(Of IntPtr)
<DllImport("User32")> Private Shared Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As Integer) As Integer
End Function
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As IntPtr, ByVal lpWindowText As String, ByVal cch As Integer) As Integer
Public Declare Function SetActiveWindow Lib "user32" (ByVal hwnd As Integer) As Integer
Declare Auto Function SetForegroundWindow Lib "USER32.DLL" _
(ByVal hWnd As IntPtr) As Boolean
Public Function GetActiveWindows() As ObjectModel.Collection(Of IntPtr)
ListView1.Items.Clear()
'listcount = 0
EnumWindows(AddressOf Enumerator, 0)
Return ActiveWindows
End Function
Private Function Enumerator(ByVal hwnd As Integer, ByVal lParam As Integer) As Boolean
Dim intwidth As Integer
Dim strItemText As String
Dim objItem As ListViewItem
Dim text As String = Space(Int16.MaxValue)
If IsWindowVisible(hwnd) Then
GetWindowText(hwnd, text, Int16.MaxValue) 'Get error here stating "Option Strict On disallows
'implicit conversions from 'system.intptr to integer
'Debug.Print(text & vbCrLf)
If GetWindowText(hwnd, text, Int16.MaxValue) > 0 Then
ListView1.View = View.Details
If listcount = 0 Then
listcount = 1
intwidth = ListView1.Width - 5
ListView1.Columns.Add("WinNum", 25)
ListView1.Columns.Add("Name", 800)
'ListView1.Columns.Add("WinNum2", CInt(intwidth / 16))
'ListView1.Columns.Add("Name2", CInt(intwidth / 16))
Else
'strItemText = cname:"
objItem = ListView1.Items.Add(GetWindowText(hwnd, text, Int16.MaxValue))
' Debug.Print(GetWindowText(hwnd, text, Int16.MaxValue) & "TEXT: " & text & "hwnd:= " & hwnd & vbCrLf)
With objItem
.SubItems.Add(text)
.SubItems.Add("555-555-5555")
.SubItems.Add("555-555-5555")
.ImageIndex = 0
End With
'ListView1.Items.Add(text)
End If
End If
End If
If text.Contains("File Download") Then
Debug.Print(GetWindowText(hwnd, text, Int16.MaxValue) & "Download file found: " & text & "hwnd:= " & hwnd & vbCrLf)
'MsgBox("Hello- " & text)
xAsIntPtr = hwnd
LookForAndCloseIEPopup() '(GetWindowText(hwnd, text, Int16.MaxValue))
End If
Return True
'Add some list view items.ListView1.Items.Add(GetWindowText(hwnd, text, Int16.MaxValue))
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
GetActiveWindows()
End Sub
Sub ClickButton(ByVal WindowHandle As IntPtr)
SetActiveWindow(xAsIntPtr)
SendMessageW(WindowHandle, WM_ACTIVATE, New IntPtr(WA_ACTIVE), IntPtr.Zero)
SendMessageW(WindowHandle, BM_CLICK, IntPtr.Zero, IntPtr.Zero)
End Sub
Sub LookForAndCloseIEPopup()
'get a handle to any popup window associated with the main form (as is a popup window
'displayed by the Web browser control)...
Dim ptrDialogWindow As IntPtr = GetWindow(xAsIntPtr, GW_ENABLEDPOPUP)
Dim text2 = GetWindowText(xAsIntPtr)
Debug.Print(GetWindowText(ptrDialogWindow) & "TEXT:=" & Text2 & vbCrLf)
'if the popup window is one displayed by the browser, then send the close message to the window...
If text2.Contains("File Download") Then ClosePopup(ptrDialogWindow)
End Sub
Sub ClosePopup(ByVal WindowHandle As IntPtr)
Dim clsChildHandles As ArrayList = GetChildWindowHandles(WindowHandle)
Dim teststr As String
Dim prthandleint As Long
'look through all of the child handles of the window for an "OK" button (this method
'can also be used to gather more specific information about the dialog itself, such as
'the message being displayed)...
For Each ptrHandle As IntPtr In clsChildHandles
'if the SAVE button is found, click it...
teststr = GetWindowText(ptrHandle)
prthandleint = ptrHandle
Debug.Print(teststr & " = Child TEXT: len=" & teststr.Length & "handle = " & prthandleint & vbCrLf)
If teststr.Contains("&Save") Then
SetForegroundWindow(ptrHandle)
ClickButton(ptrHandle)
Exit For
Else
Debug.Print(teststr & " = ELSE Child TEXT: len=" & vbCrLf)
End If
Next
End Sub
Const WM_GETTEXT As Long = &HD
Const WM_GETTEXTLENGTH As Long = &HE
Const GW_ENABLEDPOPUP As Long = 6
Const BM_CLICK = &HF5
Const GW_CHILD As Long = 5
Const GW_HWNDNEXT As Long = 2
Const WM_ACTIVATE = &H6
Const WA_ACTIVE = &H1
Public Const BM_SETSTATE = &HF3
Public Const WM_LBUTTONDOWN = &H201
Public Const WM_LBUTTONUP = &H202
Public Const WM_COMMAND = &H111
'function to retrieve the popup window associated with the form, as well as to find the child windows of the popup...
Private Declare Auto Function GetWindow Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal uCmd As Integer) As IntPtr
<DllImport("user32.dll", EntryPoint:="SendMessageW")>
Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
End Function
'sendmessage overload that is used to send messages to the button on the dialog window...
Private Declare Auto Function SendMessage Lib "user32.dll" Alias "SendMessage" (ByVal hWnd As IntPtr, ByVal Msg As Integer,
ByVal wParam As Integer, ByRef lParam As IntPtr) As IntPtr
'sendmessage overloads used to retrieve the window text...
Private Declare Auto Function SendMessageA Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal Msg As Integer,
ByVal wParam As IntPtr, ByRef lParam As IntPtr) As IntPtr
<DllImport("User32.dll", CharSet:=CharSet.Auto, EntryPoint:="SendMessage")> Public Shared Function SendMessageString(ByVal hwnd As IntPtr,
ByVal wMsg As Integer, ByVal wparam As Integer, ByVal lparam As System.Text.StringBuilder) As IntPtr
End Function
Function GetChildWindowHandles(ByVal ParentWindowHandle As IntPtr) As ArrayList
Dim b As Boolean
Dim ptrChild As IntPtr
Dim clsRet As New ArrayList
'ParentWindowHandle = IntPtr(xAsIntPtr)
'get first child handle...
ptrChild = GetChildWindowHandle(xAsIntPtr)
Do Until ptrChild.Equals(IntPtr.Zero)
'add to collection of handles...
clsRet.Add(ptrChild)
'get next child...
ptrChild = GetNextWindowHandle(ptrChild)
Loop
'return...
Return clsRet
End Function
Function GetChildWindowHandle(ByVal ParentWindowHandle As IntPtr) As IntPtr
Return GetWindow(ParentWindowHandle, GW_CHILD)
End Function
Function GetNextWindowHandle(ByVal CurrentWindowhandle As IntPtr) As IntPtr
Return GetWindow(CurrentWindowhandle, GW_HWNDNEXT)
End Function
'this function returns the text of the window, used so that we can confirm that we have the right dialog window...
Function GetWindowText(ByVal WindowHandle As IntPtr) As String
Dim ptrRet As IntPtr
Dim ptrLength As IntPtr
'get length for buffer...
ptrLength = SendMessageA(WindowHandle, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero)
'create buffer for return value...
Dim sb As New System.Text.StringBuilder(ptrLength.ToInt32 + 1)
'get window text...
ptrRet = SendMessageString(WindowHandle, WM_GETTEXT, ptrLength.ToInt32 + 1, sb)
'get return value...
Return sb.ToString
End Function
Public Function MakeLParam(ByVal LoWord As Int32, ByVal HiWord As Int32) As Int32
Return (HiWord << 16) Or (LoWord And &HFFFF)
End Function
End Class
ASKER
When you download a file that opens a Windows window tagged 'Save download' ( OPEN ' SAVE ' CANCEL ) and not a browser window!
Are you saying webdriver can act on a windows window? Remember that I don`t have access to the file directly its created on the fly!
Pete
Are you saying webdriver can act on a windows window? Remember that I don`t have access to the file directly its created on the fly!
Pete
When you download a file that opens a Windows window tagged 'Save download' ( OPEN ' SAVE ' CANCEL ) and not a browser window!hmm, how should that be possible with a normal web site?
Are you saying webdriver can act on a windows window? Remember that I don`t have access to the file directly its created on the fly!What has downloading of a file on the client to do with its life cylce on the server?
Why don't you explain what you're trying to do concretly? And confirm or reject my assumption (the question mark was intenional). I had to guess, cause
I click a button to load an Excel file from a website via a Export to excel menu choice!does not tell us where you're doing this. It guess IE from the method names on your code snippet.
p.s. a comment about your code: You should separate Win32 API stuff from your normal code. Create a separate module or shared class for it. The file where you do this is often called NativeMethods.
ASKER
From my web browser (visual basic) I open a website that shows me the data I need with an option to export the data to excel.
When I click on the export to excel (via code), a window opens and asks if I want to OPEN,SAVE, or CANCEL. When my code clicks save
it doesn't go to the next step (Asking where I would like to save the code) util sub closes. I assume there must be a way to flush the
buffers that tell windows I chose the save button so I can continue with the next step which is to fill in where to save the file!
Another option is to use multi threading to start the next step to monitor for the save to window which can take from instant to 30 seconds to open!
Pete
When I click on the export to excel (via code), a window opens and asks if I want to OPEN,SAVE, or CANCEL. When my code clicks save
it doesn't go to the next step (Asking where I would like to save the code) util sub closes. I assume there must be a way to flush the
buffers that tell windows I chose the save button so I can continue with the next step which is to fill in where to save the file!
Another option is to use multi threading to start the next step to monitor for the save to window which can take from instant to 30 seconds to open!
Pete
You need to hook into IDownloadManager of your WebBrowser control.
ASKER
From what I can tell, To use Idownloadmanager you need to know the filename of the file to download.
The Excel file I'm downloading doesn't exist until I click the export to excel link.
I'm going to do it with multi-threading!
Pete
The Excel file I'm downloading doesn't exist until I click the export to excel link.
I'm going to do it with multi-threading!
Pete
Actually pressing buttons you do nothing more then sending request to the server. Check out request content (using Fiddler or other tool) and repeat it using WebClient (or HttpWebRequest).
This question needs an answer!
Become an EE member today
7 DAY FREE TRIALMembers can start a 7-Day Free trial then enjoy unlimited access to the platform.
View membership options
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
You're trying to download a file from a web site by automating IE yourself?
If this is correct, why don't you do it the official way and use webdriver? Webdriver is the current cross-browser browser intreaction interface. An other option would be classic Ie automation using hooking into IE and call the actions in the DOM directly.