如何截获网卡的 启用/禁用连接 的事件?
不知道钩子可以实现吗? 如果可以, 要用哪种类型的钩子? 哪个消息?
或者有其他方法?

解决方案 »

  1.   

    try WMI Ndis events 
      

  2.   

    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"
      

  3.   

    对于你所要的,那就\root\WMI:
    select * from MSNdis_StatusMediaDisconnect
    select * from MSNdis_StatusMediaConnect
      

  4.   

    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.
      

  5.   

    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;   
      

  6.   

    非常感谢大家的支持, 最近查阅了一些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时表示已连接。