IPConfigEx






4.50/5 (11投票s)
一个 ipconfig 和 arp 命令之间的简单混合。
1. 引言
本文旨在介绍 IP Helper API 和 Winsock API。演示项目名为 IPConfigEx,因为它实现了 “ipconfig” [^] 命令的基本功能以及 “arp” [^]) 命令的一些功能,并能将显示的信息作为电子邮件发送。
2. 本文和项目的动机
我需要一个工具,能够发送一封包含 Windows 计算机(Win2K、WinXP)网络设置的电子邮件,并且该应用程序无需复杂的安装程序或依赖项即可运行。我查看了 WinPCap [^],但它对我来说是过度杀伤,并且需要安装 WinPCap。 IP Helper API [^] 是解决方案。
3. IPConfigEx 工具的使用方法
由于这是一个命令行工具,用户通过命令行开关控制其行为。在没有任何参数的情况下,该工具将显示网络适配器列表,然后是 ARP 条目列表。
常用的命令行开关
[-i:ip] - shows information about the network adapters
[-i:arp] - show the ARP table
我实现了默认参数驱动的电子邮件发送功能,只需指定目标电子邮件即可。
4. IP Helper API 方法的讨论
项目的主干围绕 GetAdaptersInfo
和 GetIpNetTable
方法构建。如 MSDN 所述:
GetAdaptersInfo
函数检索本地计算机的适配器信息。GetIpNetTable
函数检索 IP 到物理地址的映射表。
我在这里不详述这些方法的具体实现;任何有兴趣的人都应该查阅提供的源代码。这很简单。
5. 枚举网络适配器
GetAdaptersInfo
调用返回适配器信息结构的链接列表。直观易懂。
// Loops through the network adapters list and fills the adapters vector
// with an AdapterEntry structure for each NIC.
void AdapterInfo::EnumAdapters()
{
IP_ADAPTER_INFO* pAdapterList = NULL;
IP_ADAPTER_INFO* pAdapter = NULL;
ULONG ulBufLen = 0;
DWORD err = ERROR_SUCCESS;
// clear the network adapters vector
adapters.clear();
// the first call to GetAdaptersInfo will fail and
// fills the ulBufLen with the required size
err = ::GetAdaptersInfo(pAdapterList, &ulBufLen);
if (err == ERROR_BUFFER_OVERFLOW)
{
// allocate memory for the linked adapters of IP_ADAPTER_INFO structures
pAdapterList = (IP_ADAPTER_INFO*) ::HeapAlloc(::GetProcessHeap(),
HEAP_ZERO_MEMORY, ulBufLen);
err = ::GetAdaptersInfo(pAdapterList, &ulBufLen);
}
else if (err != ERROR_SUCCESS)
{
fprintf(stderr, "EnumAdapters error. Code: %d\n", err);
return;
}
if (pAdapterList == NULL)
{
// error HeapAlloc returned NULL
fprintf(stderr, "Can't allocate memory on heap "
"(%d bytes): EnumAdapters\n", ulBufLen);
return;
}
// enumerate the network adapters
pAdapter = pAdapterList;
while (pAdapter != NULL)
{
AdapterEntry adapterEntry;
adapterEntry.index = pAdapter->Index;
adapterEntry.name = pAdapter->AdapterName;
adapterEntry.description = pAdapter->Description;
adapterEntry.mac = IpHelper::HrMacAddress(pAdapter->Address,
pAdapter->AddressLength);
adapterEntry.ip = pAdapter->IpAddressList.IpAddress;
adapterEntry.subnet = pAdapter->IpAddressList.IpMask;
// check if gateway is present
if (strlen(pAdapter->GatewayList.IpAddress.String) > 0)
adapterEntry.gateway = pAdapter->GatewayList.IpAddress;
else
ZeroMemory(&adapterEntry.gateway, 16);
// dhcp
adapterEntry.dhcpEnabled = pAdapter->DhcpEnabled ? true : false;
if (adapterEntry.dhcpEnabled)
adapterEntry.dhcpServer = pAdapter->DhcpServer.IpAddress;
// try to get the dns server list
this->EnumDnsServers(adapterEntry);
// if the adapter isn't in the adapters dictionary insert it
if (adapters.find(adapterEntry.index) == adapters.end())
adapters[adapterEntry.index] = adapterEntry;
// go on to the next adapter item
pAdapter = pAdapter->Next;
}
::HeapFree(::GetProcessHeap(), 0, pAdapterList);
}
再次来自 MSDN:
“此函数返回的列表中适配器出现的顺序可以从“网络连接”文件夹中控制:在“高级”菜单上选择“高级设置”菜单项。”
我尝试并更改了网络适配器的顺序,但适配器的索引并未改变。
6. 需要注意的事项
第一个版本是使用 Visual Studio 2005 构建的。但是,构建的可执行文件需要安装 Visual C++ 2005 可再发行组件包。使用 Visual Studio 2003 构建的相同项目可以在所有 Win2K 和 WinXP 系统上正常运行。直到此时我才知道这一点。
SMTP 消息类使用 Winsock 方法发送电子邮件。因此,为此,您需要将 *ws2_32.lib* 添加到您的项目中(链接器 -> 输入 -> 其他依赖项)。对于 IP Helper API,您需要将 *iphlpapi.lib* 添加为依赖项。
7. 待办事项
- 添加显示计算机主机名的可能性。
- 检查是否有方法知道接口上没有链接(介质已断开连接)。
- 更详细的命令行开关。