很多人都头疼过一个问题就是:在webbrowser中的对话框怎么屏蔽? 比如<script>alert('test')</script>这种弹出来一个对话框,内容为test(HTML里面的Javascript,懂网页的人应该都明白)。对于这种的屏蔽网上有两种方式:
1、在BeforeNavixxxx的事件中执行 webbrowser.Document.parentWindow.execScript "function alert(){return;}","Javascript" 。大概意思就是执行在webbrowser中执行一句JavaScript,把alert这个弹窗的函数重写了,执行的时候直接return。优点是杀人于无形,主动过滤,缺点是貌似不能屏蔽script在frame中的弹窗。。。
2、模拟点击弹窗的那个确定按钮。SendKey 什么xxxx的,具体记不清了。。。优点是肯定能点掉,缺点是必须先弹出来,被动的。
后来想到能不能通过API HOOK的方式,把弹窗的那个API做掉了岂不是更好更方便。第一反应这个函数是MessageBox函数,结果测试竟然不是。。。然后百度+Google都没有有用的信息。算了,我自己来吧。使用的windbg,终于找到了这个函数 MessageBoxIndirectW 。接下来思路就清晰了,就是干掉这个API啦,下面就是PowerBasic的API HOOK代码。
#COMPILE DLL
#DIM ALL
%USEMACROS = 1
#INCLUDE "Win32API.inc"
#INCLUDE "HookApi.Inc"
TYPE MSGBOXPARAMS
cbSize AS LONG
hWndOwner AS LONG
hInstance AS LONG
lpszText AS ASCIIZ PTR
lpszCaption AS ASCIIZ PTR
dwStyle AS LONG
lpszIcon AS ASCIIZ PTR
dwContextHelpId AS LONG
lpfnMsgBoxCallback AS LONG
dwLanguageId AS LONG
END TYPE
DECLARE FUNCTION MessageBoxIndirectW LIB "USER32.DLL" ALIAS "MessageBoxIndirectW" (lpMsgBoxParams AS MSGBOXPARAMS) AS LONG
GLOBAL ghInstance AS DWORD
GLOBAL MyMsgBoxNextHook AS DWORD
'-------------------------------------------------------------------------------
' Main DLL entry point called by Windows...
'
FUNCTION LIBMAIN (BYVAL hInstance AS LONG, _
BYVAL fwdReason AS LONG, _
BYVAL lpvReserved AS LONG) AS LONG
SELECT CASE fwdReason
CASE %DLL_PROCESS_ATTACH
ghInstance = hInstance
CALL HookAPI("user32.dll","MessageBoxIndirectW",CODEPTR(MyMsgBox),MyMsgBoxNextHook) '就是这个API MessageBoxIndirectW
FUNCTION = 1 'success!
CASE %DLL_PROCESS_DETACH
FUNCTION = 1 'success!
CASE %DLL_THREAD_ATTACH
FUNCTION = 1 'success!
CASE %DLL_THREAD_DETACH
FUNCTION = 1 'success!
END SELECT
END FUNCTION
FUNCTION MyMsgBox(lpMsgBoxParams AS MSGBOXPARAMS) AS LONG '自己重写的这个API
DIM lResult AS LONG
MSGBOX ASCToStr(lpMsgBoxParams.@lpszText),,"拦截到弹窗的内容"
MSGBOX ASCToStr(lpMsgBoxParams.@lpszCaption),,"拦截到弹窗的标题"
MSGBOX STR$(lpMsgBoxParams.dwStyle),,"拦截到弹窗的类型" '多弹了几下 大家看看就明白了
CALL DWORD MyMsgBoxNextHook USING MessageBoxIndirectW(lpMsgBoxParams) TO lResult '调用
FUNCTION = lResult '如果想要做掉这个函数 就直接写Function=0 并且把上面的注释掉就是了
END FUNCTION
FUNCTION ASCToStr(lpASC AS ASCIIZ) AS STRING '一个转换字符串的函数 大家不用管了
LOCAL TmpStr AS STRING
LOCAL lng AS LONG
lng=lstrlenW(lpASC) * 2
TmpStr=SPACE$(lng)
MoveMemory BYVAL STRPTR(TmpStr),BYVAL VARPTR(lpASC),lng
FUNCTION = ACODE$(TmpStr)
END FUNCTION
PB里直接编译生成DLL,在VB里直接LOADLIBRARY调用即可。
还有问题可以咨询我。