这个问题困扰我2天了,求大神帮忙。
http://hi.baidu.com/vansbluge/item/91ff45abb394b99f14107335
最初是看了这片文章,代码如下。
#include <Wbemidl.h>
#pragma comment(lib,"Wbemuuid.lib")HRESULT XXXDialog::EnableDHCPOnAdapter()
{
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
hr = CoInitializeSecurity(NULL,-1,NULL,NULL,RPC_C_AUTHN_LEVEL_PKT_PRIVACY,RPC_C_IMP_LEVEL_IMPERSONATE,NULL,EOAC_SECURE_REFS,NULL);HRESULT hr;
IWbemLocator *pLocator = NULL;
IWbemServices *pNamespace = NULL;
IWbemClassObject *pClass = NULL;
IWbemClassObject *pInputParamClass = NULL;
IWbemClassObject *pInputParamInstance = NULL;
IWbemClassObject *pOutInst = NULL;BSTR InstancePath = SysAllocString(L"Win32_NetworkAdapterConfiguration.Index=8"); //index为网卡号
BSTR Path = SysAllocString(L"root\\cimv2");
BSTR ClassPath = SysAllocString(L"Win32_NetworkAdapterConfiguration");
BSTR MethodName1 = SysAllocString(L"SetDNSServerSearchOrder");
BSTR MethodName2 = SysAllocString(L"EnableDHCP");
LPCWSTR MethodName1ArgName = L"DNSServerSearchOrder";hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (void **)&pLocator);
hr = pLocator->ConnectServer(Path,NULL, NULL, NULL, 0, NULL, NULL, &pNamespace);
hr = CoSetProxyBlanket( pNamespace,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE);if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pNamespace->GetObject(ClassPath, 0, NULL, &pClass, NULL);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pClass->GetMethod(MethodName1, 0, &pInputParamClass, NULL);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pInputParamClass->SpawnInstance(0, &pInputParamInstance);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pInputParamInstance->Put(MethodName1ArgName, 0, NULL, 0);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pNamespace->ExecMethod(InstancePath, MethodName1, 0, NULL, pInputParamInstance, &pOutInst, NULL);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pNamespace->ExecMethod(InstancePath, MethodName2, 0, NULL, NULL, &pOutInst, NULL);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}SysFreeString(InstancePath);
SysFreeString(Path);
SysFreeString(ClassPath);
SysFreeString(MethodName1);
SysFreeString(MethodName2);if(pOutInst)
pOutInst->Release();
if(pInputParamInstance)
pInputParamInstance->Release();
if(pInputParamClass)
pInputParamClass->Release();
if(pClass)
pClass->Release();
if(pNamespace)
pNamespace->Release();
if(pLocator)
pLocator->Release();CoUninitialize();return hr;
}我直接将这段搬过来,但是发现多个网卡是会出问题,其中注释了 //index为网卡序列号的那一句,有index=8,这个8不知道怎么回事,当只有一块网卡的时候8就可以,而且改成其他的2 3 4什么的还不行,并不是随意的一个值。我的笔记本有两块网卡,结果就出问题了,不能正常工作。
后来我参照http://www.codeproject.com/Questions/387500/Cplusplus-WMI-EnableStatic-with-multiple-IPs
将index用实际的index代替,用拼字符串的方式拼起来,但是结果依然不对,其实前几天是发现可以的,当时还高兴的以为解决了,现在发现有不行了,是在太郁闷了,求各位高手帮忙,在这个基础上修改也可以,或者提供其他的方法也可以,解决了的话我会另外捐赠100分给你,拜托了...另外我是问题是将DNS由静态改为自动DHCP方式,请看清楚,不要回答专门用来修改IP地址的方法,谢谢!
http://hi.baidu.com/vansbluge/item/91ff45abb394b99f14107335
最初是看了这片文章,代码如下。
#include <Wbemidl.h>
#pragma comment(lib,"Wbemuuid.lib")HRESULT XXXDialog::EnableDHCPOnAdapter()
{
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
hr = CoInitializeSecurity(NULL,-1,NULL,NULL,RPC_C_AUTHN_LEVEL_PKT_PRIVACY,RPC_C_IMP_LEVEL_IMPERSONATE,NULL,EOAC_SECURE_REFS,NULL);HRESULT hr;
IWbemLocator *pLocator = NULL;
IWbemServices *pNamespace = NULL;
IWbemClassObject *pClass = NULL;
IWbemClassObject *pInputParamClass = NULL;
IWbemClassObject *pInputParamInstance = NULL;
IWbemClassObject *pOutInst = NULL;BSTR InstancePath = SysAllocString(L"Win32_NetworkAdapterConfiguration.Index=8"); //index为网卡号
BSTR Path = SysAllocString(L"root\\cimv2");
BSTR ClassPath = SysAllocString(L"Win32_NetworkAdapterConfiguration");
BSTR MethodName1 = SysAllocString(L"SetDNSServerSearchOrder");
BSTR MethodName2 = SysAllocString(L"EnableDHCP");
LPCWSTR MethodName1ArgName = L"DNSServerSearchOrder";hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (void **)&pLocator);
hr = pLocator->ConnectServer(Path,NULL, NULL, NULL, 0, NULL, NULL, &pNamespace);
hr = CoSetProxyBlanket( pNamespace,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE);if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pNamespace->GetObject(ClassPath, 0, NULL, &pClass, NULL);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pClass->GetMethod(MethodName1, 0, &pInputParamClass, NULL);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pInputParamClass->SpawnInstance(0, &pInputParamInstance);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pInputParamInstance->Put(MethodName1ArgName, 0, NULL, 0);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pNamespace->ExecMethod(InstancePath, MethodName1, 0, NULL, pInputParamInstance, &pOutInst, NULL);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pNamespace->ExecMethod(InstancePath, MethodName2, 0, NULL, NULL, &pOutInst, NULL);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}SysFreeString(InstancePath);
SysFreeString(Path);
SysFreeString(ClassPath);
SysFreeString(MethodName1);
SysFreeString(MethodName2);if(pOutInst)
pOutInst->Release();
if(pInputParamInstance)
pInputParamInstance->Release();
if(pInputParamClass)
pInputParamClass->Release();
if(pClass)
pClass->Release();
if(pNamespace)
pNamespace->Release();
if(pLocator)
pLocator->Release();CoUninitialize();return hr;
}我直接将这段搬过来,但是发现多个网卡是会出问题,其中注释了 //index为网卡序列号的那一句,有index=8,这个8不知道怎么回事,当只有一块网卡的时候8就可以,而且改成其他的2 3 4什么的还不行,并不是随意的一个值。我的笔记本有两块网卡,结果就出问题了,不能正常工作。
后来我参照http://www.codeproject.com/Questions/387500/Cplusplus-WMI-EnableStatic-with-multiple-IPs
将index用实际的index代替,用拼字符串的方式拼起来,但是结果依然不对,其实前几天是发现可以的,当时还高兴的以为解决了,现在发现有不行了,是在太郁闷了,求各位高手帮忙,在这个基础上修改也可以,或者提供其他的方法也可以,解决了的话我会另外捐赠100分给你,拜托了...另外我是问题是将DNS由静态改为自动DHCP方式,请看清楚,不要回答专门用来修改IP地址的方法,谢谢!
现在是索引有问题对吧,这里有段GetAdaptersInfo(获取网卡信息的函数)代码#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#pragma comment(lib,"Iphlpapi.lib")
int main()
{
// 初始化winsock
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = NULL;
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = (PIP_ADAPTER_INFO)malloc(ulOutBufLen);
DWORD dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen);
// 第一次调用GetAdapterInfo获取ulOutBufLen大小
if (dwRetVal == ERROR_BUFFER_OVERFLOW)
{
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutBufLen);
dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen);
}
if (dwRetVal == NO_ERROR)
{
pAdapter = pAdapterInfo;
while (pAdapter)
{
printf("Adapter Name: \t%s\n", pAdapter->AdapterName);
printf("Adapter Desc: \t%s\n", pAdapter->Description);
printf("MAC Addr: \t%02x-%02x-%02x-%02x-%02x-%02x\n",
pAdapter->Address[0],
pAdapter->Address[1],
pAdapter->Address[2],
pAdapter->Address[3],
pAdapter->Address[4],
pAdapter->Address[5]);
printf("IP Address: \t%s\n", pAdapter->IpAddressList.IpAddress.String);
printf("IP Mask: \t%s\n", pAdapter->IpAddressList.IpMask.String);
printf("Gateway: \t%s\n", pAdapter->GatewayList.IpAddress.String);
pAdapter = pAdapter->Next;
}// end while
}
else
{
printf("Call to GetAdaptersInfo failed.\n");
}
...卸载winsock ...
return 0;
} //end mainPIP_ADAPTER_INFO 这玩样是链表存的。typedef struct _IP_ADAPTER_INFO {
struct _IP_ADAPTER_INFO* Next;//指向链表中下一个适配器信息的指针
DWORD ComboIndex;//预留值
char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];//使用ANSI字符串表示的适配器名称
char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];//使用ANSI字符串表示的适配器描述
UINT AddressLength;//适配器硬件地址以字节计算的长度
BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];//硬件地址以BYTE数组所表示
DWORD Index;//适配器索引
UINT Type;//适配器类型
UINT DhcpEnabled;//指定这个适配器是否开启DHCP
PIP_ADDR_STRING CurrentIpAddress;//预留值
IP_ADDR_STRING IpAddressList;//该适配器的IPv4地址链表
IP_ADDR_STRING GatewayList;//该适配器的网关IPv4地址链表
IP_ADDR_STRING DhcpServer;//该适配器的DHCP服务器的IPv4 地址链表
BOOL HaveWins;
IP_ADDR_STRING PrimaryWinsServer;
IP_ADDR_STRING SecondaryWinsServer;
time_t LeaseObtained;
time_t LeaseExpires;
} IP_ADAPTER_INFO,把这玩样拿去放入你的参数中吧。
如果楼主要偷懒
for (int i=0;i<11;i++)
{
//更改InstancePath的值
hr = pNamespace->ExecMethod(InstancePath, MethodName1, 0, NULL, pInputParamInstance, &pOutInst, NULL);
hr = pNamespace->ExecMethod(InstancePath, MethodName2, 0, NULL, NULL, &pOutInst, NULL);
}
即可只不过将所有的网卡都设置一下而已
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_Process"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);IWbemServices 这玩样可以用SQL语句。不错,不用像我一楼这么饶了
BOOL CMainDlg::GetAutoIP(CString strAdapaterName, int nSel)
{
PIP_INTERFACE_INFO pInfo;
pInfo = (IP_INTERFACE_INFO *) malloc( sizeof(IP_INTERFACE_INFO) );
memset(pInfo, 0, sizeof(IP_INTERFACE_INFO));
ULONG ulOutBufLen = 0;
DWORD dwRetVal = 0; // Make an initial call to GetInterfaceInfo to get
// the necessary size into the ulOutBufLen variable
if ( GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER) {
GlobalFree(pInfo);
pInfo = (IP_INTERFACE_INFO *) malloc (ulOutBufLen);
} // Make a second call to GetInterfaceInfo to get the
// actual data we want
if ((dwRetVal = GetInterfaceInfo(pInfo, &ulOutBufLen)) == NO_ERROR ) {
printf("\tAdapter Name: %ws\n", pInfo->Adapter[0].Name);
printf("\tAdapter Index: %ld\n", pInfo->Adapter[0].Index);
printf("\tNum Adapters: %ld\n", pInfo->NumAdapters);
}
else {
printf("GetInterfaceInfo failed.\n");
PrintError(dwRetVal);
return FALSE; }
int i=0;
for(i=0;i<pInfo->NumAdapters; i++)
{
CString strName = pInfo->Adapter[i].Name;
if(strName.Find(strAdapaterName)!=-1)
break;
}
ULONG Index = pInfo->Adapter[i].Index;
EnableDHCPOnAdapter(nSel, Index);//这里将Index传到那个问题中的函数。
// wchar_t temp[100]=L"\Device\Tcpip_{1D892EAD-A2C6-4990-A0E7-D4A9C14ADFE9}";
// memcpy(pInfo->Adapter[0].Name, (void*)temp, lstrlen(temp)); // Call IpReleaseAddress and IpRenewAddress to release and renew
// the IP address on the specified adapter.r
if ((dwRetVal = IpReleaseAddress(&pInfo->Adapter[i])) == NO_ERROR)
{
printf("IP release succeeded.\n");
}
else
{
PrintError(dwRetVal);
::MessageBox(NULL, _T("Ip release failed"), L"", MB_OK);
//return FALSE;
} if ((dwRetVal = IpRenewAddress(&pInfo->Adapter[i])) == NO_ERROR)
{
printf("IP renew succeeded.\n");
}
else
{
PrintError(dwRetVal);
::MessageBox(NULL, _T("Ip renew failed"), L"", MB_OK);
//return FALSE; }
return TRUE;
}
HRESULT CMainDlg::EnableDHCPOnAdapter(int nSel, DWORD fIndex)
{
HRESULT hr;
IWbemLocator *pLocator = NULL;
IWbemServices *pSvc = NULL;
IWbemClassObject *pClass = NULL;
IWbemClassObject *pInputParamClass = NULL;
IWbemClassObject *pInputParamInstance = NULL;
IWbemClassObject *pOutInst = NULL;
IEnumWbemClassObject * pEnumerator = NULL; hr = CoInitializeEx(0, COINIT_MULTITHREADED);
hr = CoInitializeSecurity(NULL,-1,NULL,NULL,RPC_C_AUTHN_LEVEL_PKT_PRIVACY,RPC_C_IMP_LEVEL_IMPERSONATE,NULL,EOAC_SECURE_REFS,NULL);
char indexString[10];
itoa(fIndex, indexString, 10); char instanceString[100];
wchar_t w_instanceString[100];
strcpy(instanceString, "Win32_NetworkAdapterConfiguration.Index='");
strcat(instanceString, indexString);
strcat(instanceString, "'");
mbstowcs(w_instanceString, instanceString, 100);
BSTR InstancePath = SysAllocString(w_instanceString);
//BSTR InstancePath = SysAllocString(L"Win32_NetworkAdapterConfiguration.Index='8'"); //index为网卡号
BSTR Path = SysAllocString(L"root\\cimv2");
BSTR ClassPath = SysAllocString(L"Win32_NetworkAdapterConfiguration");
BSTR MethodName1 = SysAllocString(L"SetDNSServerSearchOrder");
BSTR MethodName2 = SysAllocString(L"EnableDHCP");
LPCWSTR MethodName1ArgName = L"DNSServerSearchOrder"; hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (void **)&pLocator);
hr = pLocator->ConnectServer(Path,NULL, NULL, NULL, 0, NULL, NULL, &pSvc);
hr = CoSetProxyBlanket( pSvc,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE); if(!SUCCEEDED(hr))
{
//PrintWMIError(hr);
//PrintError(hr)
return hr;
}
if(SUCCEEDED(hr))
hr = pSvc->GetObject(ClassPath, 0, NULL, &pClass, NULL);
if(!SUCCEEDED(hr))
{
// PrintWMIError(hr);
//GetErrorInfo()
return hr;
}
if(SUCCEEDED(hr))
hr = pClass->GetMethod(MethodName1, 0, &pInputParamClass, NULL);
if(!SUCCEEDED(hr))
{
// PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pInputParamClass->SpawnInstance(0, &pInputParamInstance);
if(!SUCCEEDED(hr))
{
// PrintWMIError(hr`);
return hr;
}
if(SUCCEEDED(hr))
hr = pInputParamInstance->Put(MethodName1ArgName, 0, NULL, 0);
if(!SUCCEEDED(hr))
{
//PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pSvc->ExecMethod(InstancePath, MethodName1, 0, NULL, pInputParamInstance, &pOutInst, NULL);
if(!SUCCEEDED(hr))
{
PrintWMIError(hr);
return hr;
}
if(SUCCEEDED(hr))
hr = pSvc->ExecMethod(InstancePath, MethodName2, 0, NULL, NULL, &pOutInst, NULL);
if(!SUCCEEDED(hr))
{
//PrintWMIError(hr);
return hr;
} SysFreeString(InstancePath);
SysFreeString(Path);
SysFreeString(ClassPath);
SysFreeString(MethodName1);
SysFreeString(MethodName2); if(pOutInst)
pOutInst->Release();
if(pInputParamInstance)
pInputParamInstance->Release();
if(pInputParamClass)
pInputParamClass->Release();
if(pClass)
pClass->Release();
if(pSvc)
pSvc->Release();
if(pLocator)
pLocator->Release(); CoUninitialize();
//GetAutoIP(m_vectorAdapterInfo[nSel]->strName);
// if(GetAutoIP())
// {
// MessageBox(_T("自动获取IP成功"));
// return TRUE;
// }else
// {
// MessageBox(_T("自动获取IP失败,正在恢复设置"));
// RecoverySetting(nSel);
// }
//
//system( "net start \"dhcp client\" ");
//system ("net start dhcpserver"); //CtrlNetcard(FALSE);
//CtrlNetcard(TRUE);
//MessageBox(_T("自动获取IP成功"));
return 0;
}HRESULT __fastcall UnicodeToAnsi(LPCOLESTR pszW, LPSTR* ppszA)
{ ULONG cbAnsi, cCharacters;
DWORD dwError; // If input is null then just return the same.
if (pszW == NULL)
{
*ppszA = NULL;
return NOERROR;
} cCharacters = wcslen(pszW)+1;
// Determine number of bytes to be allocated for ANSI string. An
// ANSI string can have at most 2 bytes per character (for Double
// Byte Character Strings.)
cbAnsi = cCharacters*2; // Use of the OLE allocator is not required because the resultant
// ANSI string will never be passed to another COM component. You
// can use your own allocator.
*ppszA = (LPSTR) CoTaskMemAlloc(cbAnsi);
if (NULL == *ppszA)
return E_OUTOFMEMORY; // Convert to ANSI.
if (0 == WideCharToMultiByte(CP_ACP, 0, pszW, cCharacters, *ppszA,
cbAnsi, NULL, NULL))
{
dwError = GetLastError();
CoTaskMemFree(*ppszA);
*ppszA = NULL;
return HRESULT_FROM_WIN32(dwError);
}
return NOERROR; }
void PrintWMIError(HRESULT hr)
{
IWbemStatusCodeText * pStatus = NULL;
HRESULT hres = CoCreateInstance(CLSID_WbemStatusCodeText, 0,
CLSCTX_INPROC_SERVER,IID_IWbemStatusCodeText, (LPVOID *) &pStatus);
if(S_OK == hres)
{
BSTR bstrError;
hres = pStatus-> GetErrorCodeText(hr, 0, 0, &bstrError);
if(S_OK != hres)
bstrError = SysAllocString(L"Get last error failed");
LPSTR pszStatusTextA;
UnicodeToAnsi(bstrError, &pszStatusTextA);
printf( "%s\n ",pszStatusTextA);
CoTaskMemFree(pszStatusTextA);
pStatus-> Release();
SysFreeString(bstrError);
}
}
你等等,我去找找有其他资料嘛。
之所有要绕一下查到Index,是因为我发现Win32_NetworkAdapterConfiguration.SettingId='{4D-.....5c}';这种写法总算出错,错误为“无效参数”,所有我还是绕一下查到Index来搞。
现在问题解决了,WMI的用法也更清晰了,非常感谢!捐赠分也已经送过去了,请查收。