C++ WMI EnableStatic с несколькими IP-адресами не работает
Добрый День Всем,
Я пытался заставить функцию EnableStatic работать с несколькими IP-адресами/сетевыми масками, и у меня возникли проблемы. Ни в коем случае я не получаю никаких ошибок ни в одном из вызовов функций, но ни одна из моих переданных пар IP/Netmask на самом деле не программируется. Надеюсь, что кто-то здесь может иметь представление о том, что я, возможно, делаю неправильно или упускаю.
Код для выполнения C++ EnableStatic был основан на этой статье в разделе сообщений из "Brian Clow For God's Sake 10:38 30 May '06":
Создание запросов WMI на языке C++[^]
Я изменил эту функцию, чтобы вместо этого взять список IP/сетевых масок и построить из них параметры EnableStatic.
Вот код (есть еще некоторая очистка, которую нужно сделать в возвратах ошибок для вызовов функций, но я сначала пытался заставить его работать):
typedef struct IP_INFO { char ip[40]; char netmask[40]; } IP_INFO, *PIP_INFO; bool AddIPAddressToAdapterPersistant(PIP_INFO &ipInfo, INT count, INT fIndex) { HRESULT hr; IWbemLocator *pLocator = NULL; IWbemServices *pNamespace = NULL; BSTR path = SysAllocString(L"ROOT\\CIMV2"); // Initialize COM and connect to WMI. hr = CoInitialize(0); if(FAILED(hr)) { return (false); } // if hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); if(FAILED(hr)) { CoUninitialize(); return(false); } // if hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLocator); if (FAILED(hr)) { CoUninitialize(); return (false); } // if hr = pLocator->ConnectServer(path, NULL, NULL, NULL, 0, NULL, NULL, &pNamespace); if(FAILED(hr)) { pLocator->Release(); CoUninitialize(); return(false); } // if // Grab class required to work on Win32_NetworkAdapterConfiguration IWbemClassObject *pClass = NULL; BSTR ClassPath = SysAllocString(L"Win32_NetworkAdapterConfiguration"); hr = pNamespace->GetObject(ClassPath, 0, NULL, &pClass, NULL); SysFreeString(ClassPath); if( WBEM_S_NO_ERROR == hr ) { // Grab pointer to the input parameter class of the method we are going to call BSTR MethodName_ES = SysAllocString(L"EnableStatic"); IWbemClassObject *pInClass_ES = NULL; if(WBEM_S_NO_ERROR == pClass->GetMethod(MethodName_ES, 0, &pInClass_ES, NULL)) { // Spawn instance of the input parameter class, so that we can stuff our parameters in IWbemClassObject *pInInst_ES = NULL; if(WBEM_S_NO_ERROR == pInClass_ES->SpawnInstance(0, &pInInst_ES)) { // // (Step 3) - Pack desired parameters into the input class instances // // Convert from multibyte strings to wide character arrays wchar_t tmp_ip[_countof(ipInfo->ip)]; SAFEARRAY *ip_list = SafeArrayCreateVector(VT_BSTR, 0, count); // Insert into safe arrays, allocating memory as we do so (destroying the safe array will destroy the allocated memory) long idx[] = {0}; for(int i = 0; i < count; i++) { mbstowcs(tmp_ip, ipInfo[i].ip, _countof(ipInfo[i].ip)); BSTR ip = SysAllocString(tmp_ip); idx[0] = i; if(FAILED(SafeArrayPutElement(ip_list, idx, ip))) { return (false); } // if // Destroy the BSTR pointer SysFreeString(ip); } // for // Convert from multibyte strings to wide character arrays wchar_t tmp_netmask[_countof(ipInfo->netmask)]; SAFEARRAY *netmask_list = SafeArrayCreateVector(VT_BSTR, 0, count); // Insert into safe arrays, allocating memory as we do so (destroying the safe array will destroy the allocated memory) for(int i = 0; i < count; i++) { mbstowcs(tmp_netmask, ipInfo[i].netmask, _countof(ipInfo[i].netmask)); BSTR netmask = SysAllocString(tmp_netmask); idx[0] = i; if(FAILED(SafeArrayPutElement(netmask_list, idx, netmask))) { return (false); } // if // Destroy the BSTR pointer SysFreeString(netmask); } // for // Now wrap each safe array in a VARIANT so that it can be passed to COM function VARIANT arg1_ES; VariantInit(&arg1_ES); arg1_ES.vt = VT_ARRAY|VT_BSTR; arg1_ES.parray = ip_list; VARIANT arg2_ES; VariantInit(&arg2_ES); arg2_ES.vt = VT_ARRAY|VT_BSTR; arg2_ES.parray = netmask_list; if((WBEM_S_NO_ERROR == pInInst_ES->Put(L"IPAddress", 0, &arg1_ES, 0)) && (WBEM_S_NO_ERROR == pInInst_ES->Put(L"SubNetMask", 0, &arg2_ES, 0))) { // // (Step 4) - Call the methods // // First build the object path that specifies which network adapter we are executing a method on 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); // Now call the method IWbemClassObject * pOutInst = NULL; hr = pNamespace->ExecMethod(InstancePath, MethodName_ES, 0, NULL, pInInst_ES, &pOutInst, NULL); if(FAILED(hr)) { // false return(false); } // if SysFreeString(InstancePath); } // if // Clear the variants - does this actually get ride of safearrays? VariantClear(&arg1_ES); VariantClear(&arg2_ES); // Destroy safe arrays, which destroys the objects stored inside them SafeArrayDestroy(ip_list); ip_list = NULL; SafeArrayDestroy(netmask_list); netmask_list = NULL; } else { // false } // if // Free up the instances that we spawned if(pInInst_ES) { pInInst_ES->Release(); pInInst_ES = NULL; } // if } else { // false } // if // Free up methods input parameters class pointers if(pInClass_ES) { pInClass_ES->Release(); pInClass_ES = NULL; } // if SysFreeString(MethodName_ES); } else { // false } // if // Variable cleanup if (pNamespace) { pNamespace->Release(); pNamespace = NULL; } if (pLocator) { pLocator->Release(); pLocator = NULL; } // if if(pClass) { pClass->Release(); pClass = NULL; } //if CoUninitialize(); return(true); }
Спасибо!
Member 10557037
Tipp: для лучшего обзора может быть хорошей идеей создать функцию seaparate, которая строит SAFEARRAY из массива строк.
Member 13339507
Можете ли вы поделиться исходным кодом?
Я пытаюсь сделать что-то подобное, но не могу.
kj_easy_DN
Работает ли это все еще в Windows 10?
Я скопировал исходный код без каких-либо изменений и просто добавил такую основную функцию:
IP_INFO ipData[1];
strcpy_s (ipData[0].ip, sizeof(ipData[0].ip), "10.0.2.15");
strcpy_s (ipData[0].netmask, sizeof(ipData[0].netmask), "255.255.255.0");
PIP_INFO pipData = &(ipData[0]);
bool ret = AddIPAddressToAdapterPersistant(pipData, 1, 1);
Я один прошел через всю процедуру, каждый вызов возвращался нормально, но в конце концов конфигурация одного и единственного сетевого адаптера не была изменена.
Я проверил это с помощью ipconfig/all и, открыв страницу панель управления/сетевая карта/свойства, TCP/IPv4.
Все осталось по-прежнему, ничего не изменилось.
kj_easy_DN
Ну, мне пришлось запустить студию разработчиков в качестве администратора. Тогда все шло хорошо.
Пожалуйста, смотрите мой пост ниже, как немного улучшить образец, чтобы получить некоторые подсказки о причине вызова, который возвращает hr=S_OK, но, похоже, не имеет "никакого эффекта".