在Internet Explorer中使用VB.Net捕获Javascript警报
本文关键字:Net 捕获 Javascript 警报 VB Internet Explorer | 更新日期: 2023-09-27 18:18:31
我在这里发现了一个类似的问题,但答案没有被询问者分享。
我使用SHDocVw。InternetExplorer的api在我的Vb。. Net WinForms应用程序记录ie浏览器在我的应用程序中的用户操作。
- 我如何知道在ie浏览器中打开了javascript警告?
- 如何获取该警告框的文本?
我不想注入任何javascript。有什么方法可以让我直接知道警报打开,并通过某种方式将其挂钩以获取其文本?
编辑1:windowstatechange事件在ie浏览器中打开javascript警报时触发,但在许多其他情况下也会触发此事件,例如打开模态对话框窗口,最小化ie浏览器等。
使用下面的代码,您可以自动关闭JavaScript警报窗口,获取消息文本或发送点击消息到警报窗口上的按钮。
WindowStateChanged事件不触发JavaScript警报显示(在我的环境中)。如果触发,可以使用下面的代码。
<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function GetForegroundWindow() As IntPtr
End Function
Private Sub aaxWebBrowser1_WindowStateChanged(sender As Object, e As AxSHDocVw.DWebBrowserEvents2_WindowStateChangedEvent)
HandleJavascriptAlertwindows(GetForegroundWindow(), False)
End Sub
或者您可以使用ForeGroundWindowWatcher类来捕获JavaScript警报窗口。如果AxWebbrowser在一个表单上,你应该改变Me.ParentForm。处理到Me。处理
Private ForeGroundWindowWatcher_ As ForeGroundWindowWatcher
Private Sub StartForeGroundWatcher()
ForeGroundWindowWatcher_ = New ForeGroundWindowWatcher
AddHandler ForeGroundWindowWatcher_.ForegroundWindowHasChanged, AddressOf ForeGroundWindowWatcher_ForegroundWindowHasChanged
ForeGroundWindowWatcher_.Startt()
End Sub
Private Sub StopForeGroundWatcher()
If ForeGroundWindowWatcher_ IsNot Nothing Then
RemoveHandler ForeGroundWindowWatcher_.ForegroundWindowHasChanged, AddressOf ForeGroundWindowWatcher_ForegroundWindowHasChanged
ForeGroundWindowWatcher_.Stopp()
End If
End Sub
Private Sub btnStartForeGroundWatcher_Click(sender As System.Object, e As System.EventArgs) Handles btnStartForeGroundWatcher.Click
'Should be called inside form_load event
StartForeGroundWatcher()
End Sub
Private Sub btnStopForeGroundWatcher_Click(sender As System.Object, e As System.EventArgs) Handles btnStopForeGroundWatcher.Click
'Should be called inside form_Closing event
StopForeGroundWatcher()
End Sub
Private Sub ForeGroundWindowWatcher_ForegroundWindowHasChanged(sender As Object, ForeGroundWindowHandle As IntPtr)
HandleJavascriptAlertwindows(ForeGroundWindowHandle, False)
End Sub
Private LastForeGroundWindowHandle As IntPtr = IntPtr.Zero
Private Sub HandleJavascriptAlertwindows(ForeGroundWindowHandle As IntPtr, preventFromShowing As Boolean)
Try
'source http://www.vbforums.com/showthread.php?761005-WebBrowser-Control-how-to-handle-Javascript-generated-alert-window-%28onbeforeunload%29
'Dim hwnd = FindWindow("#32770", "Windows Internet Explorer")' this finds windows from its title.
Dim hwnd = ForeGroundWindowHandle 'GetForegroundWindow() 'get the foreground window
If hwnd = IntPtr.Zero Then Return
'Get forgroundwindow cvlassname. Classname of JavaScript alert windows is "#32770"
Dim ForeGroundWindowClassName As String = ForeGroundWindowHelper.GetClassNameFromHandle(hwnd)
Dim MeHandle As IntPtr = Me.ParentForm.Handle 'use Me.Handle if ME is a form.
'Debug.WriteLine(WindowClassName)
Dim AlertMessage As String = ""
Debug.WriteLine("ForeGroundWindowHandle: " + ForeGroundWindowHandle.ToString)
Debug.WriteLine("MeHandle: " + MeHandle.ToString)
Debug.WriteLine("ForeGroundWindowClassName: " + ForeGroundWindowClassName)
If String.CompareOrdinal("#32770", ForeGroundWindowClassName) = 0 Then
If LastForeGroundWindowHandle <> IntPtr.Zero AndAlso LastForeGroundWindowHandle <> MeHandle Then
'Alert might be shown another webbrowser.
Return
End If
For Each ch As ForeGroundWindowHelper.WindowChildInfo In ForeGroundWindowHelper.GetChildWindows(hwnd)
Debug.WriteLine("Text: " + ch.Text)
Debug.WriteLine("ClassName: " + ch.ClassName)
If ch.ClassName.ToLower = "static" Then
AlertMessage = ch.Text
End If
If preventFromShowing Then
'close alert by sending ESC
SendKeys.Send("{ESC}")
'or
''send click event to specific button
'If ch.ClassName = "Button" AndAlso ch.Text = "OK" Then
' ForeGroundWindowHelper.SendClickEvet2Button(ch.hWnd)
' Exit For
'End If
End If
Next
End If
Debug.WriteLine("AlertMessage: " + AlertMessage)
LastForeGroundWindowHandle = ForeGroundWindowHandle
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
End Sub
Imports System.Runtime.InteropServices
Imports System.Text
Public Class ForeGroundWindowWatcher
'original source https://stackoverflow.com/questions/4372055/detect-active-window-changed-using-c-sharp-without-polling
'Stephen Lee Parker
Public Event ForeGroundWindowHasChanged(sender As Object, ForeGroundWindowHandle As IntPtr)
Private dele As WinEventDelegate = Nothing
Private Const WINEVENT_OUTOFCONTEXT As UInteger = 0
Private Const EVENT_SYSTEM_FOREGROUND As UInteger = 3
Private m_hhook As IntPtr = IntPtr.Zero
Public Sub Startt()
If m_hhook <> IntPtr.Zero Then
Return
End If
dele = New WinEventDelegate(AddressOf WinEventProc)
m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT)
If m_hhook = IntPtr.Zero Then
Throw New Exception("SetWinEventHook failed")
End If
End Sub
Public Sub Stopp()
If m_hhook <> IntPtr.Zero Then
UnhookWinEvent(m_hhook)
End If
End Sub
Private Delegate Sub WinEventDelegate(hWinEventHook As IntPtr,
eventType As UInteger,
hwnd As IntPtr,
idObject As Integer,
idChild As Integer,
dwEventThread As UInteger,
dwmsEventTime As UInteger)
<DllImport("user32.dll")> _
Private Shared Function SetWinEventHook(eventMin As UInteger,
eventMax As UInteger,
hmodWinEventProc As IntPtr,
lpfnWinEventProc As WinEventDelegate,
idProcess As UInteger,
idThread As UInteger,
dwFlags As UInteger) As IntPtr
End Function
<DllImport("user32.dll")> _
Private Shared Function UnhookWinEvent(hWinEventHook As IntPtr) As Boolean
End Function
Public Sub WinEventProc(hWinEventHook As IntPtr,
eventType As UInteger,
hwnd As IntPtr,
idObject As Integer,
idChild As Integer,
dwEventThread As UInteger,
dwmsEventTime As UInteger)
RaiseEvent ForeGroundWindowHasChanged(Me, hwnd)
End Sub
End Class
WebBrowser控件如何处理Javascript生成的警报窗口
Imports System.Runtime.InteropServices
Imports System.Text
Public Class ForeGroundWindowHelper
'source http://www.vbforums.com/showthread.php?761005-WebBrowser-Control-how-to-handle-Javascript-generated-alert-window-%28onbeforeunload%29
'by AgustinTRC
Public Class WindowChildInfo
Public hWnd As IntPtr
Public ClassName As String
Public Text As String
Public Sub New(hwnd As IntPtr, clsname As String, text As String)
Me.hWnd = hwnd
Me.ClassName = clsname
Me.Text = text
End Sub
End Class
Private Const BM_CLICK As Integer = &HF5
Private Const WM_ACTIVATE As Integer = &H6
Private Const WA_ACTIVE As Integer = 1
<DllImport("user32.dll", CharSet:=CharSet.Auto, EntryPoint:="FindWindow")> _
Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll", EntryPoint:="SendMessage")> _
Private Shared Function SendMessage(hwnd As IntPtr, wMsg As Integer, wParam As Integer, lParam As Integer) As IntPtr
End Function
' private...
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Shared Sub GetClassName(ByVal hWnd As System.IntPtr, ByVal lpClassName As StringBuilder, ByVal nMaxCount As Integer)
End Sub
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function GetWindowText(ByVal hwnd As IntPtr, ByVal lpString As StringBuilder, ByVal cch As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function GetWindowTextLength(ByVal hwnd As IntPtr) As Integer
End Function
Private Delegate Function EnumCallBackDelegate(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
Private Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As IntPtr) As IntPtr
Private Shared children As List(Of WindowChildInfo)
Public Shared Function GetChildWindows(ByVal hwnd As IntPtr) As List(Of WindowChildInfo)
children = New List(Of WindowChildInfo)
EnumChildWindows(hwnd, AddressOf EnumProc, Nothing)
Return children
End Function
Private Shared Function EnumProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Int32
If hwnd <> IntPtr.Zero Then
children.Add(New WindowChildInfo(hwnd, GetClassNameFromHandle(hwnd), GetText(hwnd)))
End If
Return 1
End Function
Public Shared Function GetClassNameFromHandle(ByVal hWnd As IntPtr) As String
Dim sbClassName As New StringBuilder("", 256)
Call GetClassName(hWnd, sbClassName, 256)
Return sbClassName.ToString
End Function
Private Shared Function GetText(ByVal hWnd As IntPtr) As String
Dim length As Integer = GetWindowTextLength(hWnd)
If length = 0 Then Return ""
Dim sb As New StringBuilder("", length + 1)
GetWindowText(hWnd, sb, sb.Capacity)
Return sb.ToString()
End Function
Public Shared Sub SendClickEvet2Button(ByVal hWnd As IntPtr)
' activate the button
SendMessage(hWnd, WM_ACTIVATE, WA_ACTIVE, 0)
' send button a click message
SendMessage(hWnd, BM_CLICK, 0, 0)
End Sub
End Class
注入javascript。
(function(w){
w.____oldAlert = w.alert;
w.alert = function(msg){
console.log("alert(", msg, ");");
var result = w.____oldAlert(msg);
console.log("returned ", result);
return result;
};
})(window);
类似的代码可以应用于confirm
和prompt
,因此您不必依赖许多hack,可以读取返回值。如果有一天IE决定像Chrome那样改变显示对话框的方式,你的代码仍然可以正常工作
我想如果你看看这个问题的顶部答案,你就会找到你要找的东西。这里的代码是用C编写的,但是响应者指出所有必要的信息都在那里。