这个问题困扰我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地址的方法,谢谢!

解决方案 »

  1.   

    很遗憾,我的机器上只有一块网卡,测试不了。
    现在是索引有问题对吧,这里有段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,把这玩样拿去放入你的参数中吧。
      

  2.   

    这个用wmi编程最好,可用select * from Win32_NetworkAdapterConfiguration 查询index,
    如果楼主要偷懒
    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);
    }
    即可只不过将所有的网卡都设置一下而已
      

  3.   

    IWbemServices * pSvc;
    hres = pSvc->ExecQuery(
            bstr_t("WQL"), 
            bstr_t("SELECT * FROM Win32_Process"),
            WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
            NULL,
            &pEnumerator);IWbemServices 这玩样可以用SQL语句。不错,不用像我一楼这么饶了
      

  4.   

    谢谢,我也见过select * from,可惜不知道怎么样。初学者水平太挫了,见笑了。
      

  5.   

    我看了1楼的内容,也试过了,我现在的问题不是怎样获取Index,我用你的代码获取的Index和我现在获取的Index是一致的,验证了我的Index并没有弄错,下面是我的代码,你只有一块网卡的话也可以试试,看下如果不用index=8的值,而用你自己求出来的Index能否正确的将Dns由手动设置改为自动。或者你教教我怎么用Select* from ,谢谢!
    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);     
    }
    }
      

  6.   

    3楼也是我回复的,这个可以查SQL的
    你等等,我去找找有其他资料嘛。
      

  7.   

    非常感谢你提供的资料,是非常重要的参考,拖此之福,我知道了GetAdapterInfo 或者 GetInterfaceInfo获取的Index都是没用的,这个Index是Win32_NetworkAdapterConfiguration中的Interface的值,而且只在XP上系统无效,我在笔记本是WIN7系统,验证了这一点,我开发的环境是XP等于这个就不行了,后来用非常绕的办法,因为注意到Win32_NetworkAdapterConfiguration中的SettingID 就是GetAdapterInfo获取的设备名 然后我用这个获取到的网卡名,来执行ExecQuery,查询到index,然后用这个index拼进去,结果OK了!总算成功了,高兴死我了。
    之所有要绕一下查到Index,是因为我发现Win32_NetworkAdapterConfiguration.SettingId='{4D-.....5c}';这种写法总算出错,错误为“无效参数”,所有我还是绕一下查到Index来搞。
    现在问题解决了,WMI的用法也更清晰了,非常感谢!捐赠分也已经送过去了,请查收。