VC准确地获取真实网络连接的名字(本地连接)

因为虚拟机和软件会创建网络连接,电脑就有可能有多个网络连接,用程序获取真实的操作系统的网络连接就比较困难。

原理:注册表项HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards下面会有子键,里面记录的是系统创建的对应真实网卡的网络连接的名字,但是这个名字不太友好,要做转换。

获取到了本地连接的名字之后,再配合netsh命令就可以干很多事情了,比如程序修改网卡的dns服务器地址。

上VC代码:控制台程序,可直接编译测试

目前在xp、win7、win8和win10上面测试了一遍,结果都准确。

// QueryKey - Enumerates the subkeys of key and its associated values.
//     hKey - Key whose subkeys and values are to be enumerated.

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#pragma comment(lib,"Iphlpapi.lib")
#pragma comment(lib, "Mprapi.lib")
using namespace std;

#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383

//网卡名字与连接名字的对应关系,key为网卡名字,value为连接名字
map mapAdapterNames;
const TCHAR NETWORKCARDS[MAX_KEY_LENGTH] = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards");
void QueryKey(HKEY hKey) 
{ 
	TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name
	DWORD    cbName;                   // size of name string 
	TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
	DWORD    cchClassName = MAX_PATH;  // size of class string 
	DWORD    cSubKeys=0;               // number of subkeys 
	DWORD    cbMaxSubKey;              // longest subkey size 
	DWORD    cchMaxClass;              // longest class string 
	DWORD    cValues;              // number of values for key 
	DWORD    cchMaxValue;          // longest value name 
	DWORD    cbMaxValueData;       // longest value data 
	DWORD    cbSecurityDescriptor; // size of security descriptor 
	FILETIME ftLastWriteTime;      // last write time 

	DWORD i, retCode; 

	TCHAR  achValue[MAX_VALUE_NAME]; 
	DWORD cchValue = MAX_VALUE_NAME; 

	// Get the class name and the value count. 
	retCode = RegQueryInfoKey(
		hKey,                    // key handle 
		achClass,                // buffer for class name 
		&cchClassName,           // size of class string 
		NULL,                    // reserved 
		&cSubKeys,               // number of subkeys 
		&cbMaxSubKey,            // longest subkey size 
		&cchMaxClass,            // longest class string 
		&cValues,                // number of values for this key 
		&cchMaxValue,            // longest value name 
		&cbMaxValueData,         // longest value data 
		&cbSecurityDescriptor,   // security descriptor 
		&ftLastWriteTime);       // last write time 

	// Enumerate the subkeys, until RegEnumKeyEx fails.

	if (cSubKeys)
	{
		printf( "\nNumber of subkeys: %d\n", cSubKeys);

		for (i=0; i resultString(wideSize);
	int conResult = ::MultiByteToWideChar(CP_ACP, 0, astrsrc.c_str(), -1, &resultString[0], wideSize);
	if(conResult != wideSize)
		return L"";
	return wstring(&resultString[0]);
}
//获取网卡名字与连接名字的对应关系
void GetAdapterNamesMap()
{
	/*******************************************
	*通过Iphlpapi库获取网卡信息
	********************************************/
	PIP_ADAPTER_INFO pIpAdapterInfo = (PIP_ADAPTER_INFO) malloc(sizeof(IP_ADAPTER_INFO));
	ULONG stSize = sizeof(IP_ADAPTER_INFO);
	int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);    //获得其大小

	if (ERROR_BUFFER_OVERFLOW == nRel)                      //重新申请所需要的空间
	{
		free(pIpAdapterInfo);
		pIpAdapterInfo = (PIP_ADAPTER_INFO) malloc(stSize);
		nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize); 
	}
	
	/*******************************************
	*通过mprapi库获取连接名称
	*并通过index将网卡信息和连接名称相关联
	********************************************/
	HANDLE   hMprConfig;                    //连接信息的句柄
	DWORD   dwRet=0;                        //返回值
	PIP_INTERFACE_INFO   plfTable = NULL;   //接口信息表
	DWORD   dwBufferSize=0;                 //接口信息表空间大小

	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 
		//遍历网卡信息链表,通过index匹配,找到对应关系
		for(PIP_ADAPTER_INFO pIpAdapterInfoCopy = pIpAdapterInfo; pIpAdapterInfoCopy != NULL; pIpAdapterInfoCopy = pIpAdapterInfoCopy->Next)
		{
			if(pIpAdapterInfoCopy->Index == AdaptMap.Index)
			{
				mapAdapterNames[Ascii2Unicode(pIpAdapterInfoCopy->AdapterName)] = szFriendName;
				break;
			}
		}                                      
	} 
	HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, plfTable);

	//删除网卡信息
	if(pIpAdapterInfo)
		free(pIpAdapterInfo);
}
void __cdecl _tmain(void)
{
	setlocale(LC_ALL, "chs");
	//首先获取网卡适配器的名字与本地连接名字的对应关系
	GetAdapterNamesMap();
	//再获取真实的网络连接的名字
	HKEY hKey;

	if( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
		TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"),
		0,
		KEY_READ,
		&hKey) == ERROR_SUCCESS
		)
	{
		QuerySubKeyValue(hKey);
	}

	RegCloseKey(hKey);
	system("pause");
}


你可能感兴趣的:(VC网络编程)