i will make it simple, i need to silenty (without download dialog pop up) download a file from a website through webbrowser in vb.net, i cant download using WebClient, because i have to be login in first, neither httprequest will work even login in with it first, because first it have google captcha for login, 2nd i dont want automate the login stuff ..
i have tried api stuff:
Dim hwnd = FindWindow(vbNullString, "File Download")
If hwnd <> IntPtr.Zero Then ' dialog window found
'MsgBox("yes")
' find button on dialog window: classname = "Button", text = "OK"
Dim btn = FindWindowEx(hwnd, IntPtr.Zero, "Button", "&Save")
'Dim sd = FindWindowEx(hwnd, IntPtr.Zero, )
If btn <> IntPtr.Zero Then ' button found
' activate the button on dialog first or it may not acknowledge a click msg on first try
SendMessage(btn, WM_ACTIVATE, WA_ACTIVE, 0)
' send button a click message
SendMessage(btn, BM_CLICK, 0, 0)
Else
MsgBox("button not found!")
End If
End If
so the far, it gets the windwo, also the button found, but it wont press/click on it, its like there nothing happens ..(plus: dont incourage me for sendkeys stuff, i want it silenty)
using IE: 11
Any chances that i download using httprequest by transfering the cookie (or whatver) from webbroser to http ? any workaround, please do let me know.
Related
I have a VB.NET 4.6.1 desktop app that has been using FindWindow and FindWindowEx for over 2 years with no issue to locate a MDI child window and capture the window caption text, it has worked flawlessly until recent.
The behavior now is my app can only successfully obtain the MDI client window handle if I go back to either the parent window or MDI client and click anywhere on either window, then return to my app and the process succeeds.
I have tried adding threading sleep events, running the action continuously in a loop multiple times, calling AppActivate method using process ID (thinking I just needed to execute again), my next workaround thought is to try and send a click event to the parent window prior to my action being executed or maybe to use Enumerate all child windows of the parent, hope someone can suggest something because I am at a roadblock, been doing this for years but this one doesn't make sense to me, I have the suspicion that it is related to recent ownership of the software company and them revising this section, but I have no idea why it would interfere with these root level API methods.
Sample Code:
MDIhWnd = FindWindowEx(ParenthWnd, IntPtr.Zero, "WindowsForms10.MDICLIENT.app.0.34f5582_r7_ad1", Nothing)
'Threading.Thread.Sleep(100)
'AppActivate(proc(0).Id)
If MDIhWnd = 0 Then
Threading.Thread.Sleep(100)
'Dim hw = GetTopWindow(ParenthWnd)
For i = 0 To 500
AppActivate(proc(0).Id)
MDIhWnd = FindWindowEx(ParenthWnd, IntPtr.Zero, "WindowsForms10.MDICLIENT.app.0.34f5582_r7_ad1", Nothing)
If MDIhWnd <> 0 Then
Exit For
End If
Next
End If
The solution for me was, based on the above suggestion, to use UI Automation, I
had never worked with it before, however after looking it over I gave a go and
found that it did indeed simplify my needs to capture window text from a 3rd party application window with MDI Client Interface.
Below is a lessor version in VB.NET of the process for anyone needing to do the
same thing:
Imports System.Windows.Automation
' You will also need references to UIAutomationClient, and UIAutomationTypes
Private Sub test_ui_automation()
Dim ParenthWnd As Integer = 0
Dim _AutomationElementA As System.Windows.Automation.AutomationElement = Nothing
Dim _AutomationElementB As System.Windows.Automation.AutomationElement = Nothing
Dim _AutomationElementC As System.Windows.Automation.AutomationElement = Nothing
Dim propCondition As Condition
Try
'Parent Windows Process Stuff
ParenthWnd = FindWindow(Nothing, "Application to Find")
_AutomationElementA = AutomationElement.FromHandle(ParenthWnd)
If _AutomationElementA Is Nothing Then
NotifyIcon1.BalloonTipIcon = ToolTipIcon.Error
NotifyIcon1.BalloonTipText = "Couldn't Locate Parent Window."
NotifyIcon1.Visible = True
NotifyIcon1.ShowBalloonTip(3000)
Exit Sub
End If
' MDI Client Stuff
' I used ClassNameProperty but other conditions are available
propCondition = New PropertyCondition(AutomationElement.ClassNameProperty, "WindowsForms10.MDICLIENT.app.0.34f5582_r7_ad1", PropertyConditionFlags.IgnoreCase)
_AutomationElementB = _AutomationElementA.FindFirst(TreeScope.Element Or TreeScope.Children, propCondition)
If _AutomationElementB Is Nothing Then
NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning
NotifyIcon1.BalloonTipText = "Application warning MDIClient not Available!"
NotifyIcon1.Visible = True
NotifyIcon1.ShowBalloonTip(3000)
Exit Sub
End If
' Final Stage Stuff Locate Window Containing Class with Caption
propCondition = New PropertyCondition(AutomationElement.ClassNameProperty, "WindowsForms10.Window.8.app.0.34f5582_r7_ad1", PropertyConditionFlags.IgnoreCase)
_AutomationElementC = _AutomationElementB.FindFirst(TreeScope.Element Or TreeScope.Children, propCondition)
If _AutomationElementC Is Nothing Then
NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning
NotifyIcon1.BalloonTipText = "Automation warning, MDI Details are open."
NotifyIcon1.Visible = True
NotifyIcon1.ShowBalloonTip(3000)
Exit Sub
End If
Caption = _AutomationElementC.Current.Name
' If needed you can now parse/strip any data needed from the Caption text.
' I had other processes here but could not include in the post.
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Here is my requirement which I intend to implement. There is one window application showing some icons which take me to different web sites. When I click on one of the icons, it should open an IE window and append a customized name to it.
So, before opening any website after I click on website icon, I want to check if there is already an IE window open with that customized name, if yes, bring that already opened window to the foreground. If not, open a new IE window.
I have checked various questions posted which are related to what I am looking to achieve, but am somehow not able to get it right. Below is my attempt.
For Each e In shellWins
If InStr(1, e.GetProperty("IEWindowName"), namedWindow, CompareMethod.Text) <> 0 Then
hWnd = e.HWND
myIE = e
End If
Next
If hWnd == -1
Dim p As New Process
Dim psi As New ProcessStartInfo(IEPath, webSiteURL)
p.StartInfo = psi 'Trying to open a new IE window
p.Start()
For Each ie In shellWins
If ie.hwdn = p.MainWindowHandle Then
ie.PutProperty("IEWindowName", namedWindow)
End If
Next
End if
Else
myIE.BringToForeground()
This sometime works and sometimes does not. Is there any better way to do it?
It doesn't work in which situation? Does there any error throw when it doesn't work? If there is, please tell us the detailed error information and in which line it occurs.
Besides, you could try to compare the url to check if the website is already open in IE like this:
Sub Main()
Dim shellWins As SHDocVw.ShellWindows
Dim explorer As SHDocVw.InternetExplorer
shellWins = New SHDocVw.ShellWindows
Dim SQuery As String = "https://www.example.com/"
For Each explorer In shellWins
If explorer.Application.Name = "Internet Explorer" And explorer.LocationURL.Contains(SQuery) Then
explorer.BringToForeground()
End If
Next
shellWins = Nothing
explorer = Nothing
End Sub
I have a little project that needs me to automate IE.
I've used SHDocVw.InternetExplorer class for the initial move. (attaching to IE)
But after that I want to use the Windows API to get focus to browser element and to click it.
I know that I can do this job more easy with the built in function of SHDocVw.InternetExplorer, or use 3rd party class like Watin
But this time I want to use Windows API.
This is work perfect when I open IE browser and find some links/element to click
I used the key press {TAB} to iterate thru HTML elements then read the IE status bar to get its link. Then I use the key press {ENTER} to click/execute it.
I got problem when the element that are selected by {TAB} are inside iFrame, the keypress {ENTER} not work.
Here is my sample code
Imports WindowsApplication1.win_Api
Module browser
Public Class IE
Private Shared IE As SHDocVw.InternetExplorer
Sub New(Optional ByVal url As String = "about:blank")
Dim bw As New SHDocVw.InternetExplorer
IE = bw
Try
IE.Navigate(url)
Catch ex As Exception
End Try
End Sub
Shared Sub click(byval url as string)
Dim Z As Integer = 0
Do While Z = 0
IE.Stop()
'Send keboard press TAB this API is work perfect
SendMessage(IE.HWND, WM_IME_KEYDOWN, Keys.Tab, 0)
IE.Stop()
If IE.StatusText = url Then
Z = 1
End If
Loop
For Each I As IntPtr In GetChildWindows(IE.HWND)
Dim L As Integer = 256
Dim sb As New System.Text.StringBuilder(L)
GetClassName(I, sb, L)
If sb.ToString = "Internet Explorer_Server" Then
'Send keyboard press ENTER, this work
'But not work if the element selected by TAB action is on iframe
SendMessage(I, WM_CHAR, Keys.Enter, 0)
End If
Next
End Sub
End Class
End Module
I am trying to use the sendinput API on an mdi child window in an external application to send keys/mouse input to it for mathematical operations. I have the window handle id and use setfocus windows API to setfocus on it but sendinput will not send the keys. I tab to the receiving controls which allow numeric values. In addition, I need some numeric values to be sent as decimal input such as 3.3. If you need an image of the external application, please comment below and I will post an image on my google drive account.
......
Dim hNoteThread As IntPtr = GetWindowThreadProcessId(windowids(foundid), IntPtr.Zero)
If hNoteThread <> 0 Then
MsgBox("Panel 0 found for input")
End If
' SetForegroundWindow(windowids(foundid))
If AttachThreadInput(GetCurrentThreadId(), hNoteThread, True) = True Then
SetFocus(windowids(foundid))
System.Threading.Thread.Sleep(1000)
SendKey(VK_TAB)
System.Threading.Thread.Sleep(2000)
SendKey(VK_NUMPAD2)
System.Threading.Thread.Sleep(2000)
SendKey(VK_TAB)
SendKey(VK_NUMPAD0 + VK_DECIMAL + VK_NUMPAD5)
' System.Threading.Thread.Sleep(1000)
SendKey(VK_TAB)
SendKey(VK_NUMPAD1)
' System.Threading.Thread.Sleep(1000)
SendKey(VK_TAB)
SendKey(VK_NUMPAD2)
System.Threading.Thread.Sleep(2000)
MsgBox("keys sent")
Else
MsgBox("keys not sent")
End If
Private Sub SendKey(ByVal bKey As Short)
Dim GInput(1) As INPUT
' press the key
GInput(0).type = INPUT_KEYBOARD
GInput(0).ki.wVk = bKey
GInput(0).ki.dwFlags = 0
' release the key
GInput(1).type = INPUT_KEYBOARD
GInput(1).ki.wVk = bKey
GInput(1).ki.dwFlags = KEYEVENTF_KEYUP
SendInput(2, GInput, Marshal.SizeOf(GetType(INPUT)))
End Sub
Edit: here's a link to an image so someone can figure out how the input needs to be sent:
https://drive.google.com/file/d/0BwIppJC0dxJBalp3Ykd2VzZkQ0E/edit?usp=sharing
The target controls for sending input are the Psi, D, and the other values that can be changed in Panel0 and I need to click the button too.
The problem is that send input fails to work at all and my message box displays saying that the input has been sent.
I figured out that the button was a application drawn button so it had no handle! Also, the other controls may have been drawn too. I feel so dumb. I ended up getting the handle of the mainform and subform then tabbing through the different controls except for the button. For the button: I used the RECT class to get the bottom leftcorner of the window and kept moving x until I reached the farest left corner of the button while using sendinput to click.
Please comment below if you want source. Its too big to post here.
i wan to active start button in other app, i use spy ++ to check the button styles, i c bs_pushbutton. i try to use win api to do it.i tried WM_SETFOCUS and enter key to do it, but fail
these is my code
Dim hwnd As Int32 = apiFindWindowEx(HWND_DESKTOP, 0, Nothing, "Open File - Security Warning")
Dim cwnd As Int32 = apiFindWindowEx(hwnd, 0, Nothing, "&Run")
Dim i As Integer = SendMessage(cwnd, BS_PUSHBUTTON, 0, 0)
i declare BS_PUSHBUTTON = &H1&
it is correct value for BS_PUSHBUTTON ???
how can i run the app button event??
It's unclear exactly what you're asking for in this question. I'm not sure whether you're attempting to enable a button or emulate a click to it.
Anyway, for the former you simply need to use EnableWindow():
EnableWindow( cwnd, true );
Or alternatively:
Button_Enable( cwnd, true );
For the latter you can use SetActiveWindow() and BM_CLICK:
SetActiveWindow( hwnd );
SendMessage( cwnd, BM_CLICK, 0, 0 );