You need WMI events. WMI subsystem fires them when the state of plug&play devices change. You can register for WMI events using WQL query. For example, SELECT * FROM __InstanceCreateEvent WITHIN 5 WHERE TargetInstance ISA "XX device"
对于你所要的,那就\root\WMI: select * from MSNdis_StatusMediaDisconnect select * from MSNdis_StatusMediaConnect
unit AdpUtils;interfaceuses Windows;const MAX_INTERFACE_NAME_LEN = 256; MAXLEN_PHYSADDR = 8; MAXLEN_IFDESCR = 256; MIB_IF_TYPE_OTHER = 1; MIB_IF_TYPE_ETHERNET = 6; MIB_IF_TYPE_TOKENRING = 9; MIB_IF_TYPE_FDDI = 15; MIB_IF_TYPE_PPP = 23; MIB_IF_TYPE_LOOPBACK = 24; MIB_IF_TYPE_SLIP = 28; MIB_IF_ADMIN_STATUS_UP = 1; MIB_IF_ADMIN_STATUS_DOWN = 2; MIB_IF_ADMIN_STATUS_TESTING = 3; MIB_IF_OPER_STATUS_NON_OPERATIONAL = 0; MIB_IF_OPER_STATUS_UNREACHABLE = 1; MIB_IF_OPER_STATUS_DISCONNECTED = 2; MIB_IF_OPER_STATUS_CONNECTING = 3; MIB_IF_OPER_STATUS_CONNECTED = 4; MIB_IF_OPER_STATUS_OPERATIONAL = 5;type MIB_PHYSADDR = array[0..MAXLEN_PHYSADDR - 1] of Byte; MIB_IFDESCR = array[0..MAXLEN_IFDESCR - 1] of Char; PMIB_IFROW = ^MIB_IFROW; MIB_IFROW = packed record wszName: array[0..MAX_INTERFACE_NAME_LEN - 1] of WCHAR; dwIndex, dwType, dwMtu, dwSpeed, dwPhysAddrLen: DWORD; bPhysAddr: MIB_PHYSADDR; dwAdminStatus, dwOperStatus, dwLastChange, dwInOctets, dwInUcastPkts, dwInNUcastPkts, dwInDiscards, dwInErrors, dwInUnknownProtos, dwOutOctets, dwOutUcastPkts, dwOutNUcastPkts, dwOutDiscards, dwOutErrors, dwOutQLen, dwDescrLen: DWORD; bDescr: MIB_IFDESCR; end; PMIB_IFTABLE = ^MIB_IFTABLE; MIB_IFTABLE = packed record dwNumEntries: DWORD; table: array[0..0] of MIB_IFROW; end; TAdapterStatus = record dwType, dwOperStatus: DWORD; bDescr: MIB_IFDESCR; end; TAdapterStatuses = array of TAdapterStatus;function GetIfTable(pIfTable: PMIB_IFTABLE; pdwSize: PULONG; bOrder: BOOL): DWORD; stdcall; external 'iphlpapi.dll'; function GetAdapterTypeString(const dwType: DWORD): string; function GetGetAdapterStatusString(const dwOperStatus: DWORD): string; procedure ScanAdapters(var AdapterStatuses: TAdapterStatuses);implementationvar dwSize: DWORD; pMibIfTable: PMIB_IFTABLE;function GetAdapterTypeString(const dwType: DWORD): string; begin case dwType of MIB_IF_TYPE_OTHER: Result := '其他'; MIB_IF_TYPE_ETHERNET: Result := '以太网'; MIB_IF_TYPE_TOKENRING: Result := '令牌环'; MIB_IF_TYPE_FDDI: Result := 'FDDI'; MIB_IF_TYPE_PPP: Result := 'PPP'; MIB_IF_TYPE_LOOPBACK: Result := '回路'; MIB_IF_TYPE_SLIP: Result := 'SLIP'; end; end;function GetGetAdapterStatusString(const dwOperStatus: DWORD): string; begin case dwOperStatus of MIB_IF_OPER_STATUS_NON_OPERATIONAL: Result := '掉线'; MIB_IF_OPER_STATUS_UNREACHABLE: Result := '不可达'; MIB_IF_OPER_STATUS_DISCONNECTED: Result := '断开'; MIB_IF_OPER_STATUS_CONNECTING: Result := '连接中'; MIB_IF_OPER_STATUS_CONNECTED: Result := '已连接'; MIB_IF_OPER_STATUS_OPERATIONAL: Result := '连通'; end; end;procedure ScanAdapters(var AdapterStatuses: TAdapterStatuses); var dwRetVal: DWORD; num, i: Longint; begin dwRetVal := GetIfTable(pMibIfTable, @dwSize, False); if dwRetVal = NO_ERROR then begin num := pMibIfTable^.dwNumEntries; if Length(AdapterStatuses) <> num then SetLength(AdapterStatuses, num); for i := Low(AdapterStatuses) to High(AdapterStatuses) do begin AdapterStatuses[i].dwType := pMibIfTable^.table[i].dwType; AdapterStatuses[i].dwOperStatus := pMibIfTable^.table[i].dwOperStatus; AdapterStatuses[i].bDescr := pMibIfTable^.table[i].bDescr; end; end; end;initialization GetIfTable(nil, @dwSize, False); GetMem(pMibIfTable, dwSize);
finalization FreeMem(pMibIfTable);end. unit MainForm;interfaceuses Classes, Controls, Forms, ExtCtrls, ComCtrls, AdpUtils;type TfrmMain = class(TForm) tmRefresh: TTimer; lvAdapters: TListView; procedure tmRefreshTimer(Sender: TObject); private FAdapterStatuses: TAdapterStatuses; FAdapterNum: Integer; procedure RefreshAdapterStatuses; public { Public declarations } end;var frmMain: TfrmMain;implementation{$R *.dfm}procedure TfrmMain.RefreshAdapterStatuses; var num, i: Integer; begin ScanAdapters(FAdapterStatuses); num := Length(FAdapterStatuses); if num = FAdapterNum then begin for i := 0 to num - 1 do lvAdapters.Items[i].SubItems[1] := GetGetAdapterStatusString(FAdapterStatuses[i].dwOperStatus); end else begin lvAdapters.Items.BeginUpdate; lvAdapters.Items.Clear; for i := 0 to num - 1 do begin lvAdapters.Items.Add; lvAdapters.Items[i].Caption := GetAdapterTypeString(FAdapterStatuses[i].dwType); lvAdapters.Items[i].SubItems.Add(FAdapterStatuses[i].bDescr); lvAdapters.Items[i].SubItems.Add(GetGetAdapterStatusString(FAdapterStatuses[i].dwOperStatus)); end; lvAdapters.Items.EndUpdate; FAdapterNum := num; end; end;procedure TfrmMain.tmRefreshTimer(Sender: TObject); begin RefreshAdapterStatuses; end;end.
const discVerb = '禁用(&B)'; connVerb = '启用(&A)';
function DisableEthernet(const EthName: String): Boolean; var cpFolder: Folder; nwFolder: Folder; nVerbs: FolderItemVerbs; i,j,k: integer; begin result := false; cpFolder := shell1.NameSpace(3); if cpFolder <> nil then begin for i := 0 to cpFolder.items.Count-1 do begin if cpFolder.Items.Item(i).Name = '网络和拨号连接' then begin nwFolder := cpFolder.items.item(i).GetFolder as Folder; if nwFolder <> nil then begin for j :=0 to nwFolder.items.Count-1 do begin if nwFolder.Items.Item(j).Name = EthName then begin nVerbs := nwFolder.Items.Item(j).Verbs; for k := 0 to nVerbs.Count-1 do begin if nVerbs.Item(k).Name = discVerb then begin nVerbs.Item(k).DoIt; Result := True; end; end; end; end; end; end; end; if nwFolder = nil then showmessage('Network and Dial-up Connections not found'); end else showmessage('control panel not found');
end;
function EnableEthernet(const EthName: String): Boolean; var cpFolder: Folder; nwFolder: Folder; nVerbs: FolderItemVerbs; i,j,k: integer; begin result := false; cpFolder := shell1.NameSpace(3); if cpFolder <> nil then begin for i := 0 to cpFolder.items.Count-1 do begin if cpFolder.Items.Item(i).Name = '网络和拨号连接' then begin nwFolder := cpFolder.items.item(i).GetFolder as Folder; if nwFolder <> nil then begin for j :=0 to nwFolder.items.Count-1 do begin if nwFolder.Items.Item(j).Name = EthName then begin nVerbs := nwFolder.Items.Item(j).Verbs; for k := 0 to nVerbs.Count-1 do begin if nVerbs.Item(k).Name = connVerb then begin nVerbs.Item(k).DoIt; Result := True; end; end; end; end; end; end; end; if nwFolder = nil then showmessage('Network and Dial-up Connections not found'); end else showmessage('control panel not found'); end;
非常感谢大家的支持, 最近查阅了一些wmi的资料整理如下:--wmi事件的例子: http://msdn2.microsoft.com/en-us/library/aa393013(VS.85).aspx--delphi的wmi控件: http://www.online-admin.com/wmiset.html--How to detect network connect/disconnect? http://www.online-admin.com/howtozone/network_detect_connect.html 不知道为什么,这个事不能触发!现在的解决方法是用wmi定时查询网络适配器的信息, 并检查状态字段的值:wmi namespace:root\cimv2 WQL: select * from WIN32_NetworkAdapter查询结果中有一字段名为:NetConnectionStatus, 值为0时表示断开连接, 值为1时表示已连接。
You can register for WMI events using WQL query.
For example, SELECT * FROM __InstanceCreateEvent
WITHIN 5
WHERE TargetInstance ISA "XX device"
select * from MSNdis_StatusMediaDisconnect
select * from MSNdis_StatusMediaConnect
MAX_INTERFACE_NAME_LEN = 256;
MAXLEN_PHYSADDR = 8;
MAXLEN_IFDESCR = 256;
MIB_IF_TYPE_OTHER = 1;
MIB_IF_TYPE_ETHERNET = 6;
MIB_IF_TYPE_TOKENRING = 9;
MIB_IF_TYPE_FDDI = 15;
MIB_IF_TYPE_PPP = 23;
MIB_IF_TYPE_LOOPBACK = 24;
MIB_IF_TYPE_SLIP = 28;
MIB_IF_ADMIN_STATUS_UP = 1;
MIB_IF_ADMIN_STATUS_DOWN = 2;
MIB_IF_ADMIN_STATUS_TESTING = 3;
MIB_IF_OPER_STATUS_NON_OPERATIONAL = 0;
MIB_IF_OPER_STATUS_UNREACHABLE = 1;
MIB_IF_OPER_STATUS_DISCONNECTED = 2;
MIB_IF_OPER_STATUS_CONNECTING = 3;
MIB_IF_OPER_STATUS_CONNECTED = 4;
MIB_IF_OPER_STATUS_OPERATIONAL = 5;type
MIB_PHYSADDR = array[0..MAXLEN_PHYSADDR - 1] of Byte;
MIB_IFDESCR = array[0..MAXLEN_IFDESCR - 1] of Char; PMIB_IFROW = ^MIB_IFROW;
MIB_IFROW = packed record
wszName: array[0..MAX_INTERFACE_NAME_LEN - 1] of WCHAR;
dwIndex,
dwType,
dwMtu,
dwSpeed,
dwPhysAddrLen: DWORD;
bPhysAddr: MIB_PHYSADDR;
dwAdminStatus,
dwOperStatus,
dwLastChange,
dwInOctets,
dwInUcastPkts,
dwInNUcastPkts,
dwInDiscards,
dwInErrors,
dwInUnknownProtos,
dwOutOctets,
dwOutUcastPkts,
dwOutNUcastPkts,
dwOutDiscards,
dwOutErrors,
dwOutQLen,
dwDescrLen: DWORD;
bDescr: MIB_IFDESCR;
end; PMIB_IFTABLE = ^MIB_IFTABLE;
MIB_IFTABLE = packed record
dwNumEntries: DWORD;
table: array[0..0] of MIB_IFROW;
end; TAdapterStatus = record
dwType,
dwOperStatus: DWORD;
bDescr: MIB_IFDESCR;
end;
TAdapterStatuses = array of TAdapterStatus;function GetIfTable(pIfTable: PMIB_IFTABLE; pdwSize: PULONG; bOrder: BOOL): DWORD;
stdcall; external 'iphlpapi.dll';
function GetAdapterTypeString(const dwType: DWORD): string;
function GetGetAdapterStatusString(const dwOperStatus: DWORD): string;
procedure ScanAdapters(var AdapterStatuses: TAdapterStatuses);implementationvar
dwSize: DWORD;
pMibIfTable: PMIB_IFTABLE;function GetAdapterTypeString(const dwType: DWORD): string;
begin
case dwType of
MIB_IF_TYPE_OTHER: Result := '其他';
MIB_IF_TYPE_ETHERNET: Result := '以太网';
MIB_IF_TYPE_TOKENRING: Result := '令牌环';
MIB_IF_TYPE_FDDI: Result := 'FDDI';
MIB_IF_TYPE_PPP: Result := 'PPP';
MIB_IF_TYPE_LOOPBACK: Result := '回路';
MIB_IF_TYPE_SLIP: Result := 'SLIP';
end;
end;function GetGetAdapterStatusString(const dwOperStatus: DWORD): string;
begin
case dwOperStatus of
MIB_IF_OPER_STATUS_NON_OPERATIONAL: Result := '掉线';
MIB_IF_OPER_STATUS_UNREACHABLE: Result := '不可达';
MIB_IF_OPER_STATUS_DISCONNECTED: Result := '断开';
MIB_IF_OPER_STATUS_CONNECTING: Result := '连接中';
MIB_IF_OPER_STATUS_CONNECTED: Result := '已连接';
MIB_IF_OPER_STATUS_OPERATIONAL: Result := '连通';
end;
end;procedure ScanAdapters(var AdapterStatuses: TAdapterStatuses);
var
dwRetVal: DWORD;
num, i: Longint;
begin
dwRetVal := GetIfTable(pMibIfTable, @dwSize, False);
if dwRetVal = NO_ERROR then
begin
num := pMibIfTable^.dwNumEntries;
if Length(AdapterStatuses) <> num then
SetLength(AdapterStatuses, num);
for i := Low(AdapterStatuses) to High(AdapterStatuses) do
begin
AdapterStatuses[i].dwType := pMibIfTable^.table[i].dwType;
AdapterStatuses[i].dwOperStatus := pMibIfTable^.table[i].dwOperStatus;
AdapterStatuses[i].bDescr := pMibIfTable^.table[i].bDescr;
end;
end;
end;initialization
GetIfTable(nil, @dwSize, False);
GetMem(pMibIfTable, dwSize);
finalization
FreeMem(pMibIfTable);end.
unit MainForm;interfaceuses
Classes, Controls, Forms, ExtCtrls, ComCtrls, AdpUtils;type
TfrmMain = class(TForm)
tmRefresh: TTimer;
lvAdapters: TListView;
procedure tmRefreshTimer(Sender: TObject);
private
FAdapterStatuses: TAdapterStatuses;
FAdapterNum: Integer;
procedure RefreshAdapterStatuses;
public
{ Public declarations }
end;var
frmMain: TfrmMain;implementation{$R *.dfm}procedure TfrmMain.RefreshAdapterStatuses;
var
num, i: Integer;
begin
ScanAdapters(FAdapterStatuses);
num := Length(FAdapterStatuses);
if num = FAdapterNum then
begin
for i := 0 to num - 1 do
lvAdapters.Items[i].SubItems[1] := GetGetAdapterStatusString(FAdapterStatuses[i].dwOperStatus);
end
else begin
lvAdapters.Items.BeginUpdate;
lvAdapters.Items.Clear;
for i := 0 to num - 1 do
begin
lvAdapters.Items.Add;
lvAdapters.Items[i].Caption := GetAdapterTypeString(FAdapterStatuses[i].dwType);
lvAdapters.Items[i].SubItems.Add(FAdapterStatuses[i].bDescr);
lvAdapters.Items[i].SubItems.Add(GetGetAdapterStatusString(FAdapterStatuses[i].dwOperStatus));
end;
lvAdapters.Items.EndUpdate;
FAdapterNum := num;
end;
end;procedure TfrmMain.tmRefreshTimer(Sender: TObject);
begin
RefreshAdapterStatuses;
end;end.
discVerb = '禁用(&B)';
connVerb = '启用(&A)';
function DisableEthernet(const EthName: String): Boolean;
var
cpFolder: Folder;
nwFolder: Folder;
nVerbs: FolderItemVerbs;
i,j,k: integer;
begin
result := false;
cpFolder := shell1.NameSpace(3);
if cpFolder <> nil then
begin
for i := 0 to cpFolder.items.Count-1 do
begin
if cpFolder.Items.Item(i).Name = '网络和拨号连接' then
begin
nwFolder := cpFolder.items.item(i).GetFolder as Folder;
if nwFolder <> nil then
begin
for j :=0 to nwFolder.items.Count-1 do
begin
if nwFolder.Items.Item(j).Name = EthName then
begin
nVerbs := nwFolder.Items.Item(j).Verbs;
for k := 0 to nVerbs.Count-1 do
begin
if nVerbs.Item(k).Name = discVerb then
begin
nVerbs.Item(k).DoIt;
Result := True;
end;
end;
end;
end;
end;
end;
end;
if nwFolder = nil then
showmessage('Network and Dial-up Connections not found');
end
else
showmessage('control panel not found');
end;
function EnableEthernet(const EthName: String): Boolean;
var
cpFolder: Folder;
nwFolder: Folder;
nVerbs: FolderItemVerbs;
i,j,k: integer;
begin
result := false;
cpFolder := shell1.NameSpace(3);
if cpFolder <> nil then
begin
for i := 0 to cpFolder.items.Count-1 do
begin
if cpFolder.Items.Item(i).Name = '网络和拨号连接' then
begin
nwFolder := cpFolder.items.item(i).GetFolder as Folder;
if nwFolder <> nil then
begin
for j :=0 to nwFolder.items.Count-1 do
begin
if nwFolder.Items.Item(j).Name = EthName then
begin
nVerbs := nwFolder.Items.Item(j).Verbs;
for k := 0 to nVerbs.Count-1 do
begin
if nVerbs.Item(k).Name = connVerb then
begin
nVerbs.Item(k).DoIt;
Result := True;
end;
end;
end;
end;
end;
end;
end;
if nwFolder = nil then
showmessage('Network and Dial-up Connections not found');
end
else
showmessage('control panel not found');
end;
http://msdn2.microsoft.com/en-us/library/aa393013(VS.85).aspx--delphi的wmi控件:
http://www.online-admin.com/wmiset.html--How to detect network connect/disconnect?
http://www.online-admin.com/howtozone/network_detect_connect.html
不知道为什么,这个事不能触发!现在的解决方法是用wmi定时查询网络适配器的信息, 并检查状态字段的值:wmi namespace:root\cimv2
WQL: select * from WIN32_NetworkAdapter查询结果中有一字段名为:NetConnectionStatus, 值为0时表示断开连接, 值为1时表示已连接。