65.9K
CodeProject 正在变化。 阅读更多。
Home

如何使用本机 WiFi API 访问无线网络参数

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.70/5 (10投票s)

2009年4月10日

CPOL

2分钟阅读

viewsIcon

183568

downloadIcon

6967

使用原生 WiFi API 查询无线网络参数。

引言

在之前的两篇文章中,我向您展示了如何使用 DeviceIOControl 和 Windows Management Instrumentation (WMI) 机制访问 NDIS 迷你端口驱动程序。 本文重点介绍原生 WiFi API。 原生 WiFi API 基本上是为 C/C++ 程序员设计的。 此 API 包含许多用于无线网络连接和配置文件管理的函数。

过去,程序员会使用 DeviceIOControl 或 WMI 查询 OID,以访问无线网络的各种参数。 微软通过引入原生 WiFi API 使其变得更加容易。 现在,我们无需直接查询迷你端口驱动程序。 我们可以像使用 Win32 API 一样,从我们的应用程序中使用 Wifi API。

背景

微软推出了原生 WiFi API,这是一种用于管理无线网络连接和配置文件的全新 API。 运行 Windows Vista 或 Windows XP SP2 的客户端应用程序可以使用此 API。 微软已将其 API 默认集成到 Vista 中。

Windows XP SP2 也支持一部分原生 WiFi API。 但是,用户必须安装额外的软件包/补丁,才能在 Windows XP ASP2 环境中获得此 API 支持。 您可以从 微软网站 了解更多关于 Windows XP SP2 的无线 LAN API 的信息。

使用代码

在下面的示例中,我们将看到如何使用 Wifi API 枚举无线适配器。 Wifi API 提供了许多用于查询无线网络各种参数的函数。

//
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            PlatformInvoke.wifi wifiAPI = new PlatformInvoke.wifi();
            wifiAPI.EnumerateNICs();
        }
    }
       
}
 
namespace PlatformInvoke
{
    /// <summary >
    /// This class encapsulates basic functions required
    /// for enumerating wireless adapaters in the system. This class consumes 
    /// wifi api developed and supported from Microsoft Vista onwards
    /// </summary >
    class wifi
    {
        //************************************************************
        #region declarations
 
        private const int WLAN_API_VERSION_2_0 = 2; //Windows Vista WiFi API Version
        private const int ERROR_SUCCESS = 0;
 
        /// <summary >
        /// Opens a connection to the server
        /// </summary >
        [DllImport("wlanapi.dll", SetLastError = true)]
        private static extern UInt32 WlanOpenHandle(UInt32 dwClientVersion, 
                IntPtr pReserved, out UInt32 pdwNegotiatedVersion, 
                out IntPtr phClientHandle);
 
        /// <summary >
        /// Closes a connection to the server
        /// </summary >
        [DllImport("wlanapi.dll", SetLastError = true)]
        private static extern UInt32 WlanCloseHandle(IntPtr hClientHandle, 
                                                     IntPtr pReserved);
 
        /// <summary >
        /// Enumerates all wireless interfaces in the laptop
        /// </summary >
        [DllImport("wlanapi.dll", SetLastError = true)]
        private static extern UInt32 WlanEnumInterfaces(IntPtr hClientHandle, 
                       IntPtr pReserved, out IntPtr ppInterfaceList);
 
        /// <summary >
        /// Frees memory returned by native WiFi functions
        /// </summary >
        [DllImport("wlanapi.dll", SetLastError = true)]
        private static extern void WlanFreeMemory(IntPtr pmemory);
 
        /// <summary >
        /// Interface state enums
        /// </summary >
        public enum WLAN_INTERFACE_STATE : int
        {
            wlan_interface_state_not_ready = 0,
            wlan_interface_state_connected,
            wlan_interface_state_ad_hoc_network_formed,
            wlan_interface_state_disconnecting,
            wlan_interface_state_disconnected,
            wlan_interface_state_associating,
            wlan_interface_state_discovering,
            wlan_interface_state_authenticating
        };
 
        /// <summary >
        /// Stores interface info
        /// </summary >
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct WLAN_INTERFACE_INFO
        {
            /// GUID->_GUID
            public Guid InterfaceGuid;
 
            /// WCHAR[256]
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string strInterfaceDescription;
 
            /// WLAN_INTERFACE_STATE->_WLAN_INTERFACE_STATE
            public WLAN_INTERFACE_STATE isState;
        }
        /// <summary >
        /// This structure contains an array of NIC information
        /// </summary >
       [StructLayout(LayoutKind.Sequential)]
        public struct WLAN_INTERFACE_INFO_LIST
        {
            public Int32 dwNumberofItems;
            public Int32 dwIndex;
            public WLAN_INTERFACE_INFO[] InterfaceInfo;
 
            public WLAN_INTERFACE_INFO_LIST(IntPtr pList)
            {
                // The first 4 bytes are the number of WLAN_INTERFACE_INFO structures.
                dwNumberofItems = Marshal.ReadInt32(pList, 0);
 
                // The next 4 bytes are the index of the current item in the unmanaged API.
                dwIndex = Marshal.ReadInt32(pList, 4);
 
                // Construct the array of WLAN_INTERFACE_INFO structures.
                InterfaceInfo = new WLAN_INTERFACE_INFO[dwNumberofItems];
 
                for (int i = 0; i < dwNumberofItems; i++)
                {
                    // The offset of the array of structures is 8 bytes past the beginning.
                    // Then, take the index and multiply it by the number of bytes in the
                    // structure.
                    // the length of the WLAN_INTERFACE_INFO structure is 532 bytes - this
                    // was determined by doing a sizeof(WLAN_INTERFACE_INFO) in an
                    // unmanaged C++ app.
                    IntPtr pItemList = new IntPtr(pList.ToInt32() + (i * 532) + 8);
 
                    // Construct the WLAN_INTERFACE_INFO structure, marshal the unmanaged
                    // structure into it, then copy it to the array of structures.
                    WLAN_INTERFACE_INFO wii = new WLAN_INTERFACE_INFO();
                    wii = (WLAN_INTERFACE_INFO)Marshal.PtrToStructure(pItemList,
                        typeof(WLAN_INTERFACE_INFO));
                    InterfaceInfo[i] = wii;
                }
            }
        }
 
        #endregion
 
        //************************************************************
        #region Private Functions
        /// <summary >
        ///get NIC state  
        /// </summary >
        private string getStateDescription(WLAN_INTERFACE_STATE state)
        {
            string stateDescription=string.Empty;
            switch (state)
            {
                case WLAN_INTERFACE_STATE.wlan_interface_state_not_ready:
                    stateDescription = "not ready to operate";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_connected:
                    stateDescription = "connected";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_ad_hoc_network_formed:
                    stateDescription = "first node in an adhoc network";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_disconnecting:
                    stateDescription = "disconnecting";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_disconnected:
                    stateDescription = "disconnected";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_associating:
                    stateDescription = "associating";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_discovering:
                    stateDescription = "discovering";
                    break;
                case WLAN_INTERFACE_STATE.wlan_interface_state_authenticating:
                    stateDescription = "authenticating";
                    break;
            }
 
            return stateDescription;
        }
        #endregion
 
        //************************************************************
        #region Public Functions
 
        /// <summary >
        /// enumerate wireless network adapters using wifi api
        /// </summary >
        public void EnumerateNICs()
        {
            uint serviceVersion = 0;
            IntPtr handle = IntPtr.Zero;
            if(WlanOpenHandle(WLAN_API_VERSION_2_0, IntPtr.Zero, 
                out serviceVersion, out handle) == ERROR_SUCCESS)
            {
                IntPtr ppInterfaceList = IntPtr.Zero;
                WLAN_INTERFACE_INFO_LIST interfaceList;
 
                if (WlanEnumInterfaces(handle, IntPtr.Zero, 
                              out ppInterfaceList) == ERROR_SUCCESS)
                {
                    //Tranfer all values from IntPtr to WLAN_INTERFACE_INFO_LIST structure 
                    interfaceList = new WLAN_INTERFACE_INFO_LIST(ppInterfaceList);
 
                    Console.WriteLine("Enumerating Wireless Network Adapters...");
                    for (int i = 0; i < interfaceList.dwNumberofItems; i++)
                        Console.WriteLine("{0}-->{1}", 
                          interfaceList.InterfaceInfo[i].strInterfaceDescription,
                          getStateDescription(interfaceList.InterfaceInfo[i].isState));
 
                    //frees memory
                    if (ppInterfaceList != IntPtr.Zero)
                        WlanFreeMemory(ppInterfaceList);
                }
                //close handle
                WlanCloseHandle(handle, IntPtr.Zero);
            }
        }
        #endregion
    }
}

上面的代码是用 C# 使用平台调用机制编写的,它显示了每个无线适配器的名称及其状态。

结论

本文演示了如何从 C# .NET 应用程序访问 Wifi API。 Wifi API 暴露了许多功能,您可以探索其中的每一个。

参考文献

  1. https://codeproject.org.cn/KB/system/DeviceIOControl1.aspx
  2. https://codeproject.org.cn/KB/system/WMIInterface.aspx
© . All rights reserved.