如何检测 WiFi 何时(重新)连接?
How to detect when WiFi (re)connects?
抱歉,我没有任何代码可以显示。这可能会使这个问题成为 Programmers 的候选问题,但他们这里没有语言特定区域,我正在寻找 Delphi 解决方案,所以我会在这里问。我希望这是可以接受的。
基本上,我想在 WiFi 连接时自动启动我的 VPN。我将如何检测到它? Google,看来,在这件事上不是我的朋友。
所需的 WinApi 调用未在 Delphi 中实现 - 您必须自己定义和调用它们。在这种情况下,相关功能是:
WlanRegisterNotification (MSDN)
WLAN_NOTIFICATION_SOURCE structure (MSDN)
您可以将它们定义为:
const
wlanapi = 'wlanapi.dll';
WLAN_NOTIFICATION_SOURCE_ACM = [=10=]000008;
type
GUID = TGUID;
HANDLE = THandle;
PWLanNotificationData = ^TWLanNotificationData;
TWLanNotificationData = record
NotificationSource: DWORD;
NotificationCode: DWORD;
InterfaceGuid: GUID;
dwDataSize: DWORD;
pData: PVOID;
end;
TWLanNotificationCallback = procedure(data: PWLanNotificationData; context: PVOID); stdcall;
function WlanOpenHandle(dwClientVersion: DWORD; pReserved: PVOID;
out pdwNegotiatedVersion: DWORD; out phClientHandle: HANDLE): DWORD; stdcall;
external wlanapi name 'WlanOpenHandle';
function WlanRegisterNotification(hClientHandle: HANDLE; dwNotifSource: DWORD;
bIgnoreDuplicate: BOOL; funcCallback: TWLanNotificationCallback; pCallbackContext: PVOID;
pReserved: PVOID; out pdwPrevNotifSource: DWORD): DWORD; stdcall;
external wlanapi name 'WlanRegisterNotification';
并称他们为:
// Define a callback procedure to handle the notifications
// You can supply a context pointer to any user information the callback
// may require (pointer to object, etc)
procedure OnWlanNotify(data : PWLanNotificationData; context : PVOID); stdcall;
begin
// ShowMessage(IntToStr(data^.NotificationCode)); etc...
end;
// Register for notification
procedure TForm1.FormCreate(Sender: TObject);
var
negotiatedVer : DWORD;
prevSource : DWORD
begin
if WlanOpenHandle(2, nil, negotiatedVer, FHandle) <> ERROR_SUCCESS then begin
// handle error...
end;
// check negotiatedVersion if needed
if WlanRegisterNotification(FHandle,
WLAN_NOTIFICATION_SOURCE_ACM,
LongBool(true),
@OnWlanNotify,
nil,
nil,
prevSource) <> ERROR_SUCCESS then begin
end;
这会为您注册 WLAN 通知。您的回调函数将在收到通知后执行,通知的性质可以在传递给该方法的 TWlanNotificationData
结构中找到。
您还应该取消注册不再需要的通知。我在这里只实现了基本的错误检查。可以在引用的 MSDN 文档中找到各种错误代码的详细信息。
ACM 通知的(部分)列表:
const
WLAN_NOTIFICATION_ACM_AUTOCONF_ENABLED = [=12=]000001;
//Autoconfiguration is enabled.
WLAN_NOTIFICATION_ACM_AUTOCONF_DISABLED = [=12=]000002;
//Autoconfiguration is disabled.
WLAN_NOTIFICATION_ACM_BACKGROUND_SCAN_ENABLED = [=12=]000003;
//Background scans are enabled.
WLAN_NOTIFICATION_ACM_BACKGROUND_SCAN_DISABLED = [=12=]000004;
//Background scans are disabled.
WLAN_NOTIFICATION_ACM_BSS_TYPE_CHANGE = [=12=]000005;
//The BSS type for an interface has changed.
WLAN_NOTIFICATION_ACM_POWER_SETTING_CHANGE = [=12=]000006;
//The power setting for an interface has changed.
WLAN_NOTIFICATION_ACM_SCAN_COMPLETE = [=12=]000007;
//A scan for networks has completed.
WLAN_NOTIFICATION_ACM_SCAN_FAIL = [=12=]000008;
//A scan for connectable networks failed.
WLAN_NOTIFICATION_ACM_CONNECTION_START = [=12=]000009;
//A connection has started to a network in range.
WLAN_NOTIFICATION_ACM_CONNECTION_COMPLETE = [=12=]00000a;
//A connection has completed.
WLAN_NOTIFICATION_ACM_CONNECTION_ATTEMPT_FAIL = [=12=]00000b;
//A connection attempt has failed.
WLAN_NOTIFICATION_ACM_FILTER_LIST_CHANGE = [=12=]00000c;
//A change in the filter list has occurred, either through group policy or a call to the WlanSetFilterList function.
WLAN_NOTIFICATION_ACM_INTERFACE_ARRIVAL = [=12=]00000d;
//A wireless LAN interface is been added to or enabled on the local computer.
WLAN_NOTIFICATION_ACM_INTERFACE_REMOVAL = [=12=]00000e;
//A wireless LAN interface has been removed or disabled on the local computer.
WLAN_NOTIFICATION_ACM_PROFILE_CHANGE = [=12=]00000f;
//A change in a profile or the profile list has occurred, either through group policy or by calls to Native Wifi functions.
WLAN_NOTIFICATION_ACM_PROFILE_NAME_CHANGE = [=12=]000010;
//A profile name has changed, either through group policy or by calls to Native Wifi functions.
WLAN_NOTIFICATION_ACM_PROFILES_EXHAUSTED = [=12=]000011;
//All profiles were exhausted in an attempt to autoconnect.
WLAN_NOTIFICATION_ACM_NETWORK_NOT_AVAILABLE = [=12=]000012;
//The wireless service cannot find any connectable network after a scan.
WLAN_NOTIFICATION_ACM_NETWORK_AVAILABLE = [=12=]000013;
//The wireless service found a connectable network after a scan, the interface was in the disconnected state, and there is no compatible auto-connect profile that the wireless service can use to connect .
WLAN_NOTIFICATION_ACM_DISCONNECTING = [=12=]000014;
//The wireless service is disconnecting from a connectable network.
WLAN_NOTIFICATION_ACM_DISCONNECTED = [=12=]000015;
//The wireless service has disconnected from a connectable network.
WLAN_NOTIFICATION_ACM_ADHOC_NETWORK_STATE_CHANGE = [=12=]000016;
//A state change has occurred for an adhoc network.
第二个示例回调更详细:
procedure OnWlanNotify(data : PWLanNotificationData; context : PVOID); stdcall;
begin
case data^.NotificationCode of
WLAN_NOTIFICATION_ACM_AUTOCONF_ENABLED :
TForm1(context^).Memo1.Lines.Add('Autoconfiguration is enabled.');
WLAN_NOTIFICATION_ACM_AUTOCONF_DISABLED :
TForm1(context^).Memo1.Lines.Add('Autoconfiguration is disabled.');
WLAN_NOTIFICATION_ACM_BACKGROUND_SCAN_ENABLED :
TForm1(context^).Memo1.Lines.Add('Background scans are enabled.');
WLAN_NOTIFICATION_ACM_BACKGROUND_SCAN_DISABLED :
TForm1(context^).Memo1.Lines.Add('Background scans are disabled.');
WLAN_NOTIFICATION_ACM_BSS_TYPE_CHANGE :
TForm1(context^).Memo1.Lines.Add('The BSS type for an interface has changed.');
WLAN_NOTIFICATION_ACM_POWER_SETTING_CHANGE :
TForm1(context^).Memo1.Lines.Add('The power setting for an interface has changed.');
WLAN_NOTIFICATION_ACM_SCAN_COMPLETE :
TForm1(context^).Memo1.Lines.Add('A scan for networks has completed.');
WLAN_NOTIFICATION_ACM_SCAN_FAIL :
TForm1(context^).Memo1.Lines.Add('A scan for connectable networks failed.');
WLAN_NOTIFICATION_ACM_CONNECTION_START :
TForm1(context^).Memo1.Lines.Add('A connection has started to a network in range.');
WLAN_NOTIFICATION_ACM_CONNECTION_COMPLETE :
TForm1(context^).Memo1.Lines.Add('A connection has completed.');
WLAN_NOTIFICATION_ACM_CONNECTION_ATTEMPT_FAIL :
TForm1(context^).Memo1.Lines.Add('A connection attempt has failed.');
WLAN_NOTIFICATION_ACM_FILTER_LIST_CHANGE :
TForm1(context^).Memo1.Lines.Add('A change in the filter list has occurred, either through group policy or a call to the WlanSetFilterList function.');
WLAN_NOTIFICATION_ACM_INTERFACE_ARRIVAL :
TForm1(context^).Memo1.Lines.Add('A wireless LAN interface is been added to or enabled on the local computer.');
WLAN_NOTIFICATION_ACM_INTERFACE_REMOVAL :
TForm1(context^).Memo1.Lines.Add('A wireless LAN interface has been removed or disabled on the local computer.');
WLAN_NOTIFICATION_ACM_PROFILE_CHANGE :
TForm1(context^).Memo1.Lines.Add('A change in a profile or the profile list has occurred, either through group policy or by calls to Native Wifi functions.');
WLAN_NOTIFICATION_ACM_PROFILE_NAME_CHANGE :
TForm1(context^).Memo1.Lines.Add('A profile name has changed, either through group policy or by calls to Native Wifi functions.');
WLAN_NOTIFICATION_ACM_PROFILES_EXHAUSTED :
TForm1(context^).Memo1.Lines.Add('All profiles were exhausted in an attempt to autoconnect.');
WLAN_NOTIFICATION_ACM_NETWORK_NOT_AVAILABLE :
TForm1(context^).Memo1.Lines.Add('The wireless service cannot find any connectable network after a scan.');
WLAN_NOTIFICATION_ACM_NETWORK_AVAILABLE :
TForm1(context^).Memo1.Lines.Add('The wireless service found a connectable network after a scan, the interface was in the disconnected state, and there is no compatible auto-connect profile that the wireless service can use to connect.');
WLAN_NOTIFICATION_ACM_DISCONNECTING :
TForm1(context^).Memo1.Lines.Add('The wireless service is disconnecting from a connectable network.');
WLAN_NOTIFICATION_ACM_DISCONNECTED :
TForm1(context^).Memo1.Lines.Add('The wireless service has disconnected from a connectable network.');
WLAN_NOTIFICATION_ACM_ADHOC_NETWORK_STATE_CHANGE :
TForm1(context^).Memo1.Lines.Add('A state change has occurred for an adhoc network.');
end;
end;
在上面的示例中,在用户上下文参数中传递了指向 Form1
的指针。这在回调中传回,允许您从方法中访问该数据。
if WlanRegisterNotification(FHandle,
WLAN_NOTIFICATION_SOURCE_ACM,
LongBool(true),
@OnWlanNotify,
@Form1, // Pass in form pointer
nil,
prevSource) <> ERROR_SUCCESS then begin
// handle error
end;
抱歉,我没有任何代码可以显示。这可能会使这个问题成为 Programmers 的候选问题,但他们这里没有语言特定区域,我正在寻找 Delphi 解决方案,所以我会在这里问。我希望这是可以接受的。
基本上,我想在 WiFi 连接时自动启动我的 VPN。我将如何检测到它? Google,看来,在这件事上不是我的朋友。
所需的 WinApi 调用未在 Delphi 中实现 - 您必须自己定义和调用它们。在这种情况下,相关功能是:
WlanRegisterNotification (MSDN)
WLAN_NOTIFICATION_SOURCE structure (MSDN)
您可以将它们定义为:
const
wlanapi = 'wlanapi.dll';
WLAN_NOTIFICATION_SOURCE_ACM = [=10=]000008;
type
GUID = TGUID;
HANDLE = THandle;
PWLanNotificationData = ^TWLanNotificationData;
TWLanNotificationData = record
NotificationSource: DWORD;
NotificationCode: DWORD;
InterfaceGuid: GUID;
dwDataSize: DWORD;
pData: PVOID;
end;
TWLanNotificationCallback = procedure(data: PWLanNotificationData; context: PVOID); stdcall;
function WlanOpenHandle(dwClientVersion: DWORD; pReserved: PVOID;
out pdwNegotiatedVersion: DWORD; out phClientHandle: HANDLE): DWORD; stdcall;
external wlanapi name 'WlanOpenHandle';
function WlanRegisterNotification(hClientHandle: HANDLE; dwNotifSource: DWORD;
bIgnoreDuplicate: BOOL; funcCallback: TWLanNotificationCallback; pCallbackContext: PVOID;
pReserved: PVOID; out pdwPrevNotifSource: DWORD): DWORD; stdcall;
external wlanapi name 'WlanRegisterNotification';
并称他们为:
// Define a callback procedure to handle the notifications
// You can supply a context pointer to any user information the callback
// may require (pointer to object, etc)
procedure OnWlanNotify(data : PWLanNotificationData; context : PVOID); stdcall;
begin
// ShowMessage(IntToStr(data^.NotificationCode)); etc...
end;
// Register for notification
procedure TForm1.FormCreate(Sender: TObject);
var
negotiatedVer : DWORD;
prevSource : DWORD
begin
if WlanOpenHandle(2, nil, negotiatedVer, FHandle) <> ERROR_SUCCESS then begin
// handle error...
end;
// check negotiatedVersion if needed
if WlanRegisterNotification(FHandle,
WLAN_NOTIFICATION_SOURCE_ACM,
LongBool(true),
@OnWlanNotify,
nil,
nil,
prevSource) <> ERROR_SUCCESS then begin
end;
这会为您注册 WLAN 通知。您的回调函数将在收到通知后执行,通知的性质可以在传递给该方法的 TWlanNotificationData
结构中找到。
您还应该取消注册不再需要的通知。我在这里只实现了基本的错误检查。可以在引用的 MSDN 文档中找到各种错误代码的详细信息。
ACM 通知的(部分)列表:
const
WLAN_NOTIFICATION_ACM_AUTOCONF_ENABLED = [=12=]000001;
//Autoconfiguration is enabled.
WLAN_NOTIFICATION_ACM_AUTOCONF_DISABLED = [=12=]000002;
//Autoconfiguration is disabled.
WLAN_NOTIFICATION_ACM_BACKGROUND_SCAN_ENABLED = [=12=]000003;
//Background scans are enabled.
WLAN_NOTIFICATION_ACM_BACKGROUND_SCAN_DISABLED = [=12=]000004;
//Background scans are disabled.
WLAN_NOTIFICATION_ACM_BSS_TYPE_CHANGE = [=12=]000005;
//The BSS type for an interface has changed.
WLAN_NOTIFICATION_ACM_POWER_SETTING_CHANGE = [=12=]000006;
//The power setting for an interface has changed.
WLAN_NOTIFICATION_ACM_SCAN_COMPLETE = [=12=]000007;
//A scan for networks has completed.
WLAN_NOTIFICATION_ACM_SCAN_FAIL = [=12=]000008;
//A scan for connectable networks failed.
WLAN_NOTIFICATION_ACM_CONNECTION_START = [=12=]000009;
//A connection has started to a network in range.
WLAN_NOTIFICATION_ACM_CONNECTION_COMPLETE = [=12=]00000a;
//A connection has completed.
WLAN_NOTIFICATION_ACM_CONNECTION_ATTEMPT_FAIL = [=12=]00000b;
//A connection attempt has failed.
WLAN_NOTIFICATION_ACM_FILTER_LIST_CHANGE = [=12=]00000c;
//A change in the filter list has occurred, either through group policy or a call to the WlanSetFilterList function.
WLAN_NOTIFICATION_ACM_INTERFACE_ARRIVAL = [=12=]00000d;
//A wireless LAN interface is been added to or enabled on the local computer.
WLAN_NOTIFICATION_ACM_INTERFACE_REMOVAL = [=12=]00000e;
//A wireless LAN interface has been removed or disabled on the local computer.
WLAN_NOTIFICATION_ACM_PROFILE_CHANGE = [=12=]00000f;
//A change in a profile or the profile list has occurred, either through group policy or by calls to Native Wifi functions.
WLAN_NOTIFICATION_ACM_PROFILE_NAME_CHANGE = [=12=]000010;
//A profile name has changed, either through group policy or by calls to Native Wifi functions.
WLAN_NOTIFICATION_ACM_PROFILES_EXHAUSTED = [=12=]000011;
//All profiles were exhausted in an attempt to autoconnect.
WLAN_NOTIFICATION_ACM_NETWORK_NOT_AVAILABLE = [=12=]000012;
//The wireless service cannot find any connectable network after a scan.
WLAN_NOTIFICATION_ACM_NETWORK_AVAILABLE = [=12=]000013;
//The wireless service found a connectable network after a scan, the interface was in the disconnected state, and there is no compatible auto-connect profile that the wireless service can use to connect .
WLAN_NOTIFICATION_ACM_DISCONNECTING = [=12=]000014;
//The wireless service is disconnecting from a connectable network.
WLAN_NOTIFICATION_ACM_DISCONNECTED = [=12=]000015;
//The wireless service has disconnected from a connectable network.
WLAN_NOTIFICATION_ACM_ADHOC_NETWORK_STATE_CHANGE = [=12=]000016;
//A state change has occurred for an adhoc network.
第二个示例回调更详细:
procedure OnWlanNotify(data : PWLanNotificationData; context : PVOID); stdcall;
begin
case data^.NotificationCode of
WLAN_NOTIFICATION_ACM_AUTOCONF_ENABLED :
TForm1(context^).Memo1.Lines.Add('Autoconfiguration is enabled.');
WLAN_NOTIFICATION_ACM_AUTOCONF_DISABLED :
TForm1(context^).Memo1.Lines.Add('Autoconfiguration is disabled.');
WLAN_NOTIFICATION_ACM_BACKGROUND_SCAN_ENABLED :
TForm1(context^).Memo1.Lines.Add('Background scans are enabled.');
WLAN_NOTIFICATION_ACM_BACKGROUND_SCAN_DISABLED :
TForm1(context^).Memo1.Lines.Add('Background scans are disabled.');
WLAN_NOTIFICATION_ACM_BSS_TYPE_CHANGE :
TForm1(context^).Memo1.Lines.Add('The BSS type for an interface has changed.');
WLAN_NOTIFICATION_ACM_POWER_SETTING_CHANGE :
TForm1(context^).Memo1.Lines.Add('The power setting for an interface has changed.');
WLAN_NOTIFICATION_ACM_SCAN_COMPLETE :
TForm1(context^).Memo1.Lines.Add('A scan for networks has completed.');
WLAN_NOTIFICATION_ACM_SCAN_FAIL :
TForm1(context^).Memo1.Lines.Add('A scan for connectable networks failed.');
WLAN_NOTIFICATION_ACM_CONNECTION_START :
TForm1(context^).Memo1.Lines.Add('A connection has started to a network in range.');
WLAN_NOTIFICATION_ACM_CONNECTION_COMPLETE :
TForm1(context^).Memo1.Lines.Add('A connection has completed.');
WLAN_NOTIFICATION_ACM_CONNECTION_ATTEMPT_FAIL :
TForm1(context^).Memo1.Lines.Add('A connection attempt has failed.');
WLAN_NOTIFICATION_ACM_FILTER_LIST_CHANGE :
TForm1(context^).Memo1.Lines.Add('A change in the filter list has occurred, either through group policy or a call to the WlanSetFilterList function.');
WLAN_NOTIFICATION_ACM_INTERFACE_ARRIVAL :
TForm1(context^).Memo1.Lines.Add('A wireless LAN interface is been added to or enabled on the local computer.');
WLAN_NOTIFICATION_ACM_INTERFACE_REMOVAL :
TForm1(context^).Memo1.Lines.Add('A wireless LAN interface has been removed or disabled on the local computer.');
WLAN_NOTIFICATION_ACM_PROFILE_CHANGE :
TForm1(context^).Memo1.Lines.Add('A change in a profile or the profile list has occurred, either through group policy or by calls to Native Wifi functions.');
WLAN_NOTIFICATION_ACM_PROFILE_NAME_CHANGE :
TForm1(context^).Memo1.Lines.Add('A profile name has changed, either through group policy or by calls to Native Wifi functions.');
WLAN_NOTIFICATION_ACM_PROFILES_EXHAUSTED :
TForm1(context^).Memo1.Lines.Add('All profiles were exhausted in an attempt to autoconnect.');
WLAN_NOTIFICATION_ACM_NETWORK_NOT_AVAILABLE :
TForm1(context^).Memo1.Lines.Add('The wireless service cannot find any connectable network after a scan.');
WLAN_NOTIFICATION_ACM_NETWORK_AVAILABLE :
TForm1(context^).Memo1.Lines.Add('The wireless service found a connectable network after a scan, the interface was in the disconnected state, and there is no compatible auto-connect profile that the wireless service can use to connect.');
WLAN_NOTIFICATION_ACM_DISCONNECTING :
TForm1(context^).Memo1.Lines.Add('The wireless service is disconnecting from a connectable network.');
WLAN_NOTIFICATION_ACM_DISCONNECTED :
TForm1(context^).Memo1.Lines.Add('The wireless service has disconnected from a connectable network.');
WLAN_NOTIFICATION_ACM_ADHOC_NETWORK_STATE_CHANGE :
TForm1(context^).Memo1.Lines.Add('A state change has occurred for an adhoc network.');
end;
end;
在上面的示例中,在用户上下文参数中传递了指向 Form1
的指针。这在回调中传回,允许您从方法中访问该数据。
if WlanRegisterNotification(FHandle,
WLAN_NOTIFICATION_SOURCE_ACM,
LongBool(true),
@OnWlanNotify,
@Form1, // Pass in form pointer
nil,
prevSource) <> ERROR_SUCCESS then begin
// handle error
end;