找回密码
 加入
搜索
查看: 4141|回复: 32

[网络通信] [已解决]用DllCallbackRegister注册的回调函数关闭脚本时会卡死无法正常退出

[复制链接]
发表于 2022-2-4 17:01:48 | 显示全部楼层 |阅读模式
本帖最后由 smooth 于 2022-2-6 20:53 编辑

用DllCallbackRegister注册的回调函数,回调时间设定为250毫秒,关闭脚本时会卡死无法正常退出。同样的功能,用AdlibRegister注册,调用时间一样,则不会卡死,不知道是什么原因导致的。


#include <SetupApi.au3>
Opt("GuionEventmode", 1)
Opt("WinTitleMatchMode", 2)
Local $hGUI = GUICreate("", 300, 300)
GUICtrlCreateLabel("U-KEY状态:", 30, 160, 66, 18)
Local $U_KEY_stateLabel = GUICtrlCreateLabel("", 96, 160, 60, 18)
GUICtrlCreateLabel("网银状态:", 30, 200, 60, 18)
Local $WY_stateLabel = GUICtrlCreateLabel("", 90, 200, 60, 18)
GUISetState()
GUISetOnEvent(-3, "_Exit")
$U_KEY_state = DllCallbackRegister("Monitor", "int", "hwnd;uint;uint;dword");注册一个回调函数,用来监视U-KEY插入和拔出状态和网银登录状态。"Monitor"为函数名,"int"为返回的类型,"hwnd;uint;uint;dword"为函数的参数,即该函数有4个参数,分别为:hwnd、uint、uint、dword。
$U_KEY_stateDLL = DllCall("user32.dll", "uint", "SetTimer", "hwnd", 0, "uint", 0, "int", 250, "ptr", DllCallbackGetPtr($U_KEY_state))
While 1
 Sleep(10)
WEnd 
Func Monitor($hWnd, $uiMsg, $idEvent, $dwTime);回调函数
 Local Static $sDevs0 = -100, $sLbData0
 Local $sLbData
 Local $sDevs = _DetectHardID()
 If $idEvent = $U_KEY_stateDLL[0] Then
  If $sDevs <> $sDevs0 Then
   If $sDevs <> '' Then
    GUICtrlSetData($U_KEY_stateLabel, "已插入")
   Else
    GUICtrlSetData($U_KEY_stateLabel, "未插入")
   EndIf
   $sDevs0 = $sDevs
  EndIf 
  If WinExists("浦发银行网银客户端") Then
   $sLbData = "客户端版"
  ElseIf StringInStr(WinGetTitle("上海浦东发展银行公司网上银行"), "Internet Explorer") Then
   $sLbData = "网页版(IE)"
  ElseIf StringInStr(WinGetTitle("上海浦东发展银行公司网上银行"), "用户配置") Then
   $sLbData = "网页版(Edge)"
  Else
   $sLbData = "未登录"
  EndIf
  If $sLbData0 <> $sLbData Then
   $sLbData0 = $sLbData
   GUICtrlSetData($WY_stateLabel, $sLbData0)
  EndIf
 EndIf
EndFunc   ;==>Monitor
Func _DetectHardID();检测U-KEY设备实例ID
 Local $hDevs, $tDevInfo, $aMouse[1][2] = [[0]]
 $hDevs = _SetupDiGetClassDevs($DIGCF_PRESENT, "CDROM");DiskDrive
 While _SetupDiEnumDeviceInfo($hDevs, $aMouse[0][0], $tDevInfo)
  $aMouse[0][0] += 1
  $sDescr = _SetupDiGetDeviceRegistryProperty($hDevs, $tDevInfo, $SPDRP_DEVICEDESC)
  $sName = _SetupDiGetDeviceRegistryProperty($hDevs, $tDevInfo, $SPDRP_FRIENDLYNAME)
  If $sName <> "" Then $sDescr = $sName
  ReDim $aMouse[$aMouse[0][0] + 1][2]
  $aMouse[$aMouse[0][0]][0] = $sDescr ; 磁盘描述信息
  $aMouse[$aMouse[0][0]][1] = _SetupDiGetDeviceInstanceId($hDevs, $tDevInfo) ; 设备范例ID
 WEnd
 ; 枚举网卡只需把"DiskDrive"改为"Net",鼠标则对应Mouse,光驱则为CDROM,显卡对应Display。
 _SetupDiDestroyDeviceInfoList($hDevs)
 Local $dFindDevs = ""
 For $i = 1 To $aMouse[0][0]
  If StringInStr($aMouse[$i][1], "USBSTOR\CDROM&VEN_TENDYRON&PROD_U-DISK&REV_1.10\") Then;
   $dFindDevs = $aMouse[$i][1]
   ExitLoop
  EndIf
 Next
 Return $dFindDevs;把变量值返回给函数_DetectHardID()
EndFunc   ;==>_DetectHardID
Func _Exit()
 DllCallbackFree($U_KEY_state)
 Exit
EndFunc 


发表于 2022-2-5 10:50:18 | 显示全部楼层
为什么要注册两次。。。
 楼主| 发表于 2022-2-5 19:59:06 | 显示全部楼层
本帖最后由 smooth 于 2022-2-5 20:05 编辑
haijie1223 发表于 2022-2-5 10:50
为什么要注册两次。。。

已修改为注册一次,也是无法退出,点击退出就卡死。
 楼主| 发表于 2022-2-5 20:13:56 | 显示全部楼层
haijie1223 发表于 2022-2-5 10:50
为什么要注册两次。。。

很奇怪,点击左上角,选择“关闭(C)    ALT +F4”,就可以很顺利的关闭,点击右上角的X,就卡死。
发表于 2022-2-5 20:36:16 | 显示全部楼层
Exit 前先 GUIDelete($hGUI)
 楼主| 发表于 2022-2-5 21:08:28 | 显示全部楼层
afan 发表于 2022-2-5 20:36
Exit 前先 GUIDelete($hGUI)

Exit 前先 GUIDelete($hGUI),点击关闭按钮,界面马上消失。但是这是假象,在任务管理器里面还能看到,然后过了大约7、8秒,界面又弹出来,而且再次点击关闭按钮,就卡死了。
发表于 2022-2-5 21:23:10 | 显示全部楼层
smooth 发表于 2022-2-5 21:08
Exit 前先 GUIDelete($hGUI),点击关闭按钮,界面马上消失。但是这是假象,在任务管理器里面还能看到,然 ...

你创建了定时器,退出前应先销毁
DllCall('user32.dll', 'bool', 'KillTimer', 'hwnd', 0, 'uint_ptr', $U_KEY_stateDLL[0])
 楼主| 发表于 2022-2-5 21:27:48 | 显示全部楼层
afan 发表于 2022-2-5 21:23
你创建了定时器,退出前应先销毁
DllCall('user32.dll', 'bool', 'KillTimer', 'hwnd', 0, 'uint_ptr', ...

退出前增加了这行,还是会卡死。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2022-2-5 23:37:54 | 显示全部楼层
定时器时间过短了
游客,如果您要查看本帖隐藏内容请回复

 楼主| 发表于 2022-2-6 08:17:12 | 显示全部楼层
zghwelcome 发表于 2022-2-5 23:37
定时器时间过短了
**** 本内容被作者隐藏 ****

我测试了,越短越容易卡死,越长越不容易卡死。但是太长就没有什么用了,要250毫毛以下。
发表于 2022-2-6 10:10:54 | 显示全部楼层
把 Local $sDevs = _DetectHardID() 改为 Local $sDevs = '' 也就是不检测硬件试试,这样高频次检测硬件太不合理
 楼主| 发表于 2022-2-6 10:25:01 | 显示全部楼层
afan 发表于 2022-2-6 10:10
把 Local $sDevs = _DetectHardID() 改为 Local $sDevs = '' 也就是不检测硬件试试,这样高频次检测硬件太 ...

不检测硬件就没有问题,我试过了。但是比较奇怪的是,用AdlibRegister来注册,哪怕把检测时间调到50毫秒检测一次,退出也没有什么问题。
发表于 2022-2-6 10:30:58 | 显示全部楼层
smooth 发表于 2022-2-6 10:25
不检测硬件就没有问题,我试过了。但是比较奇怪的是,用AdlibRegister来注册,哪怕把检测时间调到50毫秒 ...

你可以简单理解为 AdlibRegister 是排队,定时器是并发。
搞不懂你为何要用这种浪费资源的循环检测,之前已经提醒你用系统消息。
发表于 2022-2-6 10:46:21 | 显示全部楼层
afan 发表于 2022-2-6 10:30
你可以简单理解为 AdlibRegister 是排队,定时器是并发。
搞不懂你为何要用这种浪费资源的循环检测,之 ...

在windows下不利用windows的规则,别出心裁的玩法。。。
 楼主| 发表于 2022-2-6 10:47:02 | 显示全部楼层
afan 发表于 2022-2-6 10:30
你可以简单理解为 AdlibRegister 是排队,定时器是并发。
搞不懂你为何要用这种浪费资源的循环检测,之 ...

系统消息的实现机制,我感觉也是循环检测吧,不循环它怎么知道什么时候发生硬件改变?

另外,系统消息,它只能检测硬件变化,但是无法具体到某一个具体的硬件变化,比如某个具体的U盾插入。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-12-22 16:48 , Processed in 0.115782 second(s), 20 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表