实时注册网络适配器更改

2024-09-28 13:28:40 发布

您现在位置:Python中文网/ 问答频道 /正文

对于Python应用程序,我希望尽快对网络适配器中的更改做出反应,例如,当适配器连接或断开时,或者任何适配器的IP地址更改时。我在Windows10上

我当前的方法是使用^{}模块中的EvtSubscribe来监视事件日志Microsoft-Windows-NetworkProfile/Operational中的新条目。然而,以这种方式注册IP地址更改似乎需要1到10秒的时间,连接/断开适配器的速度比^{中图标上显示的反应时间慢约一秒

我有没有办法对这些变化做出更快的反应?我也欢迎解释为什么不可能有更快的反应


Tags: 模块方法应用程序windows方式时间事件条目
1条回答
网友
1楼 · 发布于 2024-09-28 13:28:40

我自己发现并尝试了以下三种方法。请注意,它们都是特定于Windows的。我通过插入/拔出以太网电缆以及启用/禁用WLAN来测试对连接的网络适配器的更改。连接适配器通常需要一段时间才能注册,Control Panel\Network and Internet\Network Connections中的Windows GUI也需要大约三秒的时间。我想在那里没什么可做的

网络变化

使用^{}允许从.NETAPI中的System.Net.NetworkInformation导入^{}NetworkAddressChanged事件可用于通知地址和适配器连接信息。只有当不再有适配器连接到网络时,NetworkAvailabilityChanged事件才会触发,这可能是您想要的,也可能不是您想要的。 这种方法总体上给了我最好的结果:地址更改和适配器断开连接只需不到一秒的时间就可以注册,连接适配器大约需要3.5秒。Python代码与Microsoft文档中显示的用法类似。但是,对断开连接的适配器所做的地址更改和DNS服务器更改不会触发该事件

监视注册表

使用win32api^{}允许侦听注册表项HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces(用于地址更改)和...\Tcpip\Parameters\DNSRegisteredAdapters(用于连接/断开连接)的子项中的更改。后一个条目似乎并不实际存储信息本身,而是作为副作用进行了更改。另一个缺点是注册表项中可能存在与我们正在寻找的更改无关的更改。 这种方法几乎可以即时报告地址更改(甚至比NetworkChange方法更快)。适配器连接在大约3秒时也稍微快一点。但是,适配器断开速度要慢得多,需要3秒钟多一点的时间才能注册。示例代码:

import win32api
import win32event
import win32con

def registry_wait():
    watchflags = win32api.REG_NOTIFY_CHANGE_NAME | win32api.REG_NOTIFY_CHANGE_LAST_SET
    if_key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces')
    if_evt = win32event.CreateEvent(None, 0, 0, None)
    win32api.RegNotifyChangeKeyValue(if_key, True, watchflags, if_evt, True)
    dnsada_key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DNSRegisteredAdapters')
    dnsada_evt = win32event.CreateEvent(None, 0, 0, None)
    win32api.RegNotifyChangeKeyValue(dnsada_key, True, watchflags, dnsada_evt, True)
    while True:
        ret_code = win32event.WaitForMultipleObjects([if_evt, dnsada_evt], False, win32event.INFINITE)
        if ret_code == win32con.WAIT_OBJECT_0 + 0:
            print('IP address info changed') # do something
            win32event.ResetEvent(if_evt)
            win32api.RegNotifyChangeKeyValue(if_key, True, watchflags, if_evt, True)
        elif ret_code == win32con.WAIT_OBJECT_0 + 1:
            print('Adapter info changed') # do something else
            win32event.ResetEvent(dnsada_evt)
            win32api.RegNotifyChangeKeyValue(dnsada_key, True, watchflags, dnsada_evt, True)
        else:
            break # set a timeout in WaitForMultipleObjects above
    win32api.RegCloseKey(dnsada_key)
    win32api.RegCloseKey(if_key)

查看事件日志

这是问题中提到的方法,使用EvtSubscribe侦听Microsoft-Windows-NetworkProfile/Operational事件日志。这几乎在所有方面都比其他两种方法慢。我看到地址更改需要2到10秒的时间才能被记录下来,但大部分时间大约是6到7秒。持续连接适配器大约需要4秒钟。断开适配器的连接需要1秒钟多一点的时间,在这方面超过了注册表方法。不过,网络变革方法总是更快

相关问题 更多 >

    热门问题