I am trying to develop a C++ program to programmatically configure the IIS app host configuration file, but failed to add a element to the elementcollection.
And I kept getting an error complaining that another process is accessing the same data and do not know why.
Below is the code snippet.
Any kind of advice will be appreciated.
#include "stdafx.h" #include <windows.h> #include <stdio.h> #include <ahadmin.h> #include <crtdbg.h> #include <string> using namespace std; void PrintPropertiesOfElement(IAppHostElement *pElement) { HRESULT hr = S_OK; IAppHostPropertyCollection *pProperties = NULL; IAppHostProperty *pProperty = NULL; hr = pElement->get_Properties(&pProperties); DWORD properties_count = 0; hr = pProperties->get_Count(&properties_count); VARIANT vtIndex; vtIndex.vt = VT_INT; for(DWORD i=0; i<properties_count; ++i) { vtIndex.intVal = i; hr = pProperties->get_Item(vtIndex, &pProperty); BSTR strName; BSTR strValue; hr = pProperty->get_Name(&strName); hr = pProperty->get_StringValue(&strValue); _tprintf(_T("name : %s, value: %s\n"), strName, strValue); } } void PrintElementsOfCollection(IAppHostChildElementCollection *pCollection) { HRESULT hr = S_OK; IAppHostElement *pElement = NULL; DWORD elements_count = 0; hr = pCollection->get_Count(&elements_count); VARIANT vtIndex; vtIndex.vt = VT_INT; for(DWORD i=0; i<elements_count; ++i) { vtIndex.intVal = i; hr = pCollection->get_Item(vtIndex, &pElement); BSTR strName; hr = pElement->get_Name(&strName); _tprintf(_T("element : %s\n"), strName); } } void PrintElementsOfCollection(IAppHostElementCollection *pCollection) { HRESULT hr = S_OK; IAppHostElement *pElement = NULL; DWORD elements_count = 0; hr = pCollection->get_Count(&elements_count); VARIANT vtIndex; vtIndex.vt = VT_INT; for(DWORD i=0; i<elements_count; ++i) { vtIndex.intVal = i; hr = pCollection->get_Item(vtIndex, &pElement); BSTR strName; hr = pElement->get_Name(&strName); _tprintf(_T("element : %s\n"), strName); //PrintPropertiesOfElement(pElement); } } struct UserCertification { VARIANT username; VARIANT password; VARIANT certification; public: UserCertification(wstring name, wstring pwd, wstring cert) { username.vt = VT_BSTR; username.bstrVal = SysAllocString(name.c_str()); password.vt = VT_BSTR; password.bstrVal = SysAllocString(pwd.c_str()); certification.vt = VT_BSTR; certification.bstrVal = SysAllocString(cert.c_str()); } }; HRESULT SetHostElementProperty(IAppHostElement *pElement, UserCertification *pUserCert) { HRESULT hr = S_OK; IAppHostProperty *pProperty = NULL; BSTR name = SysAllocString(L"userName"); BSTR password = SysAllocString(L"password"); BSTR certification = SysAllocString(L"certificate"); //name hr = pElement->GetPropertyByName(name, &pProperty); pProperty->put_Value(pUserCert->username); //password hr = pElement->GetPropertyByName(password, &pProperty); pProperty->put_Value(pUserCert->password); //certification hr = pElement->GetPropertyByName(certification, &pProperty); pProperty->put_Value(pUserCert->certification); return hr; } UserCertification* GenerateUserCertification() { wstring username = L"jinqiu.tao@emacle.com"; wstring password = L"123456"; wstring certificate = L"xxxxxxxx"; return new UserCertification(username, password, certificate); } int _tmain(int argc, _TCHAR* argv[]) { HRESULT hr = S_OK; IAppHostWritableAdminManager * pWMgr = NULL; IAppHostConfigManager * pCfgMgr = NULL; IAppHostConfigFile * pCfgFile = NULL; IAppHostConfigLocationCollection * pLocations = NULL; IAppHostElement *pAdminSection = NULL; IAppHostElementCollection *pElementCollection = NULL; IAppHostChildElementCollection *pChildElements = NULL; IAppHostElement *pElement = NULL; IAppHostElement *pNewElement = NULL; BSTR bstrConfigCommitPath = SysAllocString(L"MACHINE/WEBROOT/APPHOST/Default Web Site"); BSTR bstrSectionName = SysAllocString(L"system.webServer/security/authentication/iisClientCertificateMappingAuthentication"); BSTR bstrOneToOne = SysAllocString(L"oneToOneMappings"); BSTR bstrElementName = SysAllocString(L"add"); // Initialize hr = CoInitializeEx( NULL, COINIT_MULTITHREADED ); // Create hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), NULL, CLSCTX_INPROC_SERVER, __uuidof( IAppHostWritableAdminManager ), (void**) &pWMgr ); pWMgr -> put_CommitPath ( bstrConfigCommitPath ); hr = pWMgr->GetAdminSection(bstrSectionName, bstrConfigCommitPath, &pAdminSection); hr = pAdminSection->get_ChildElements(&pChildElements); PrintElementsOfCollection(pChildElements); hr = pAdminSection->GetElementByName(bstrOneToOne, &pElement); hr = pElement->get_Collection(&pElementCollection); //PrintElementsOfCollection(pElementCollection); hr = pElementCollection->CreateNewElement(bstrElementName, &pNewElement); //PrintPropertiesOfElement(pNewElement); hr = SetHostElementProperty(pNewElement, GenerateUserCertification()); //got and error saying that another process is accesssing the data hr = pElementCollection->AddElement(pNewElement); //got an error code 0x80070021 here ||||||||||||||||| PrintElementsOfCollection(pElementCollection); // Commit the changes to the configuration system pWMgr->CommitChanges ( ); return 0; }