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

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

原理:注册表项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 <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <Iphlpapi.h>
#include <Mprapi.h>
#include <string>
#include <vector>
#include <map>
#include <iostream>
#include <locale.h>

#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<wstring, wstring> 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<cSubKeys; i++) 
		{ 
			cbName = MAX_KEY_LENGTH;
			retCode = RegEnumKeyEx(hKey, i,
				achKey, 
				&cbName, 
				NULL, 
				NULL, 
				NULL, 
				&ftLastWriteTime); 
			if (retCode == ERROR_SUCCESS) 
			{
				_tprintf(TEXT("(%d) %s\n"), i+1, achKey);
			}
		}
	} 

	// Enumerate the key values. 

	if (cValues) 
	{
		printf( "\nNumber of values: %d\n", cValues);

		for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++) 
		{ 
			cchValue = MAX_VALUE_NAME; 
			achValue[0] = '\0'; 
			retCode = RegEnumValue(hKey, i, 
				achValue, 
				&cchValue, 
				NULL, 
				NULL,
				NULL,
				NULL);

			if (retCode == ERROR_SUCCESS ) 
			{ 
				_tprintf(TEXT("(%d) %s\n"), i+1, achValue); 
			} 
		}
	}
}

void QuerySubKeyValue(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<cSubKeys; i++) 
		{ 
			cbName = MAX_KEY_LENGTH;
			retCode = RegEnumKeyEx(hKey, i,
				achKey, 
				&cbName, 
				NULL, 
				NULL, 
				NULL, 
				&ftLastWriteTime); 
			if (retCode == ERROR_SUCCESS) 
			{
				_tprintf(TEXT("(%d) %s\n"), i+1, achKey);
				//生成键名				
				TCHAR szFullSubKeyName[MAX_KEY_LENGTH] = {0};
				_sntprintf(szFullSubKeyName,MAX_KEY_LENGTH,TEXT("%s\\%s"),NETWORKCARDS,achKey);
				//打开子键
				HKEY hSubKey;
				if( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
					szFullSubKeyName,
					0,
					KEY_READ,
					&hSubKey) == ERROR_SUCCESS
					)
				{
					//查询键值
					TCHAR szSubKeyValue[MAX_VALUE_NAME] = {0};
					DWORD dwType = REG_NONE, dwResultSize=MAX_VALUE_NAME * sizeof(TCHAR);
					long lResult = RegQueryValueEx(hSubKey, _T("ServiceName"), 0, &dwType, (BYTE *)(szSubKeyValue), &dwResultSize);
					if ((lResult==ERROR_SUCCESS) && (dwType==REG_SZ))
						_tprintf(mapAdapterNames[szSubKeyValue].c_str());
						//_tprintf(szSubKeyValue);
					RegCloseKey(hSubKey);
				}
			}
		}
	}
}


wstring Ascii2Unicode(string astrsrc)
{
	int wideSize = ::MultiByteToWideChar(CP_ACP, 0, astrsrc.c_str(), -1, NULL, 0);
	if (wideSize == ERROR_NO_UNICODE_TRANSLATION)
		return L"";
	if(wideSize <= 0) 
		return wstring(L"");
	//wchar_t *szbuffer = new wchar_t[nLength + 2];
	vector<wchar_t> 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");
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值