一.工具介绍
工具界面展示:本工具主要功能:
(1)能够找出所有的网卡适配器,并显示适配器的IP、MAC等信息
(2)能够修改IP、DNS、MAC等地址信息
(3)能够通过配置文件增加/删除网卡信息配置方案,并且能够根据方案进行地址切换,配置文件如下图所示:
二.IP、DNS、MAC的显示功能
2.1如何获取IP、DNS、MAC信息
主要利用Iphlpapi库获取网卡信息,Iphlpapi中IP_ADAPTER_INFO包含了IP、MAC信息但并没有包含DNS:- //获取IP地址信息
- void CIpChangeDlg::GetIpAddrsInfo()
- {
- /*******************************************
- *通过Iphlpapi库获取网卡信息和个数
- ********************************************/
- PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();
- ULONG stSize = sizeof(IP_ADAPTER_INFO);
- int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize); //获得其大小
- if (ERROR_BUFFER_OVERFLOW == nRel) //重新申请所需要的空间
- {
- delete pIpAdapterInfo;
- pIpAdapterInfo = (PIP_ADAPTER_INFO) new BYTE[stSize];
- nRel=GetAdaptersInfo(pIpAdapterInfo, &stSize);
- }
- if (ERROR_SUCCESS == nRel) //获取信息成功
- {
- m_AdapterInfo.pIpAdapterInfo = pIpAdapterInfo;
- m_AdapterInfo.iCount = 0;
- while (pIpAdapterInfo) //获取网卡个数
- {
- m_AdapterInfo.iCount++;
- pIpAdapterInfo = pIpAdapterInfo->Next;
- }
- }
- }
- //DNS,pIpAdapterInfo为网卡适配器信息结构PIP_ADAPTER_INFO
- IP_PER_ADAPTER_INFO* pPerAdapt = NULL;
- ULONG ulLen = 0;
- int err = GetPerAdapterInfo( pIpAdapterInfo->Index, pPerAdapt, &ulLen);
- if( err == ERROR_BUFFER_OVERFLOW ) {
- pPerAdapt = ( IP_PER_ADAPTER_INFO* ) HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY, ulLen);
- err = GetPerAdapterInfo( pIpAdapterInfo->Index, pPerAdapt, &ulLen );
- if( err == ERROR_SUCCESS ) {
- IP_ADDR_STRING* pNext = &( pPerAdapt->DnsServerList );
- if (pNext && strcmp(pNext->IpAddress.String, "") != 0)
- {
- m_DNSDHCPBUTTON.SetCheck(FALSE);
- m_PrimaryDnsCtl.EnableWindow(TRUE);
- m_BackupDnsCtl.EnableWindow(TRUE);
- m_PrimaryDnsCtl.SetWindowText(pNext->IpAddress.String);
- if (pNext = pNext->Next)
- m_BackupDnsCtl.SetWindowText(pNext->IpAddress.String);
- }
- else
- {
- m_DNSDHCPBUTTON.SetCheck(TRUE);
- m_PrimaryDnsCtl.EnableWindow(FALSE);
- m_BackupDnsCtl.EnableWindow(FALSE);
- m_PrimaryDnsCtl.SetWindowText("");
- m_BackupDnsCtl.SetWindowText("");
- }
- }
- HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pPerAdapt);
- }
2.2如何获得网络连接名称?
对一个网络适配器的名称有三种描述:(1)适配器对应的注册表中的一个注册表项值,称其为AdapterName;这个信息将在修改MAC的时使用;
(2)适配器描述名称,称其为AdapterDestription,比如本人主机的某一个网卡描述为:“Microsoft Virtual WiFi Miniport Adapter”;
(3)连接名称,就是在操作系统的网络连接中看到的连接名,如"本地连接"等;这个信息将在修改IP/DNS的时使用;
本工具采用netsh命令行方式进行IP/DNS的修改,命令行中进行修改的时候要指定连接名称,如"本地连接",但利用Iphlpapi库并不能获取连接名称,通过Mprapi库中的API和IP_ADAPTER_INFO中的Index 得到网卡所对应的连接名称。
- void CIpChangeDlg::GetConnectNames()
- {
- /*******************************************
- *通过mprapi库获取连接名称
- *并通过index将网卡信息和连接名称相关联
- ********************************************/
- HANDLE hMprConfig; //连接信息的句柄
- DWORD dwRet=0; //返回值
- PIP_INTERFACE_INFO plfTable = NULL; //接口信息表
- DWORD dwBufferSize=0; //接口信息表空间大小
- m_AdapterInfo.csConnectName = new char [m_AdapterInfo.iCount] [256]; //申请空间存储连接名
- dwRet = MprConfigServerConnect(NULL, &hMprConfig); //获得句柄
- dwRet = GetInterfaceInfo(NULL, &dwBufferSize); //获得接口信息表大小
- if(dwRet == ERROR_INSUFFICIENT_BUFFER) //获得接口信息
- {
- plfTable = (PIP_INTERFACE_INFO)HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY, dwBufferSize);
- GetInterfaceInfo(plfTable, &dwBufferSize);
- }
- TCHAR szFriendName[256]; //接口名称
- DWORD tchSize = sizeof(TCHAR) * 256;
- ZeroMemory(&szFriendName, tchSize);
- for (UINT i = 0; i < plfTable-> NumAdapters; i++)
- {
- IP_ADAPTER_INDEX_MAP AdaptMap; //接口信息
- AdaptMap = plfTable->Adapter[i];
- dwRet = MprConfigGetFriendlyName(hMprConfig, AdaptMap.Name,
- (PWCHAR)szFriendName, tchSize); //获得连接名称unicode
- USES_CONVERSION;
- char* pName = W2A((PWCHAR)szFriendName); //转换为ansi
- InsertConnectName(AdaptMap.Index, pName); //根据Index存储名字信息
- }
- HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, plfTable);
- }
三.IP、DNS修改
第二章节中以及提到,工具采用命令行方式进行修改;修改IP命令:
- netsh interface ip set address "连接名称" dhcp //dhcp方式
- netsh interface ip set address "连接名称" static IP地址 子网掩码 网关 //静态IP方式
- netsh interface ip set dnsservers "连接名称" dhcp //自动获取方式
- netsh interface ip set dnsservers "连接名称" static IP地址 //设置主 DNS
- netsh interface ip add dnsservers "连接名称" IP地址 //设置从属 DNS
四.MAC修改
(1)第一步寻找适配器MAC所在的注册表位置在注册表"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE- BFC1-08002bE10318}"目录下遍历寻找 与 AdapterName(2.2节中所提AdatpterName)相同的注册表项NetCfgInstanceId,则相应的MAC地址存储在相同目录 项中的NetworkAddress中。
(2)修改MAC
修改NetworkAddress中的值
(3)重启网卡
重启网卡也采用命令行方式:
- netsh interface set interface "连接名称" DISABLE //使网卡失效
- netsh interface set interface "连接名称" ENABLE //启动网卡
五.细节问题处理
5.1 命令行方式修改产生的console窗口问题
采用命令行方式来修改IP,首先想到的是
system("命令");但这种方式执行指令的时候会弹出console窗口,显然用户体验降低;那如何屏蔽窗口呢?
采用ShellExcuteEx,可以创建一个新的进程去执行修改命令,并且在程序中适用WaitForSingleObject等待进程结束。
- //启动cmd执行 netsh命令,并等待命令结束
- void CIpChangeDlg::ExcuteCommand(char* pCommandParam)
- {
- //初始化shellexe信息
- SHELLEXECUTEINFO ExeInfo;
- ZeroMemory(&ExeInfo, sizeof(SHELLEXECUTEINFO));
- ExeInfo.cbSize = sizeof(SHELLEXECUTEINFO);
- ExeInfo.lpFile = "cmd.exe";
- ExeInfo.lpParameters = pCommandParam;
- ExeInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
- ExeInfo.nShow = SW_HIDE;
- ExeInfo.hwnd = NULL;
- ExeInfo.lpVerb = NULL;
- ExeInfo.lpDirectory = NULL;
- ExeInfo.hInstApp = NULL;
- //执行命令
- ShellExecuteEx(&ExeInfo);
- //等待进程结束
- WaitForSingleObject(ExeInfo.hProcess, INFINITE);
- }
没有评论:
发表评论