创建Active Directory用户时触发IDispatch空指针异常求助
C++创建Active Directory用户时出现pDisp空指针异常
我编写C++原生代码创建Active Directory用户,代码完全照搬官方示例,但在调用pDisp->QueryInterface(IID_IADsUser, ...)时触发空指针异常,错误提示如下:
抛出异常:读取访问权限冲突。
pDisp 为空指针。
代码如下:
HRESULT CreateUserFromADs( LPCWSTR pwszName, LPCWSTR pwszSAMAccountName, LPCWSTR pwszInitialPassword) { HRESULT hr; CoInitialize(NULL); IADsContainer* pUsers = NULL; hr = ADsOpenObject(L"LDAP://WIN-F94H2MP3UJR.Test.local/CN=Users,DC=Test,DC=local", L"Administrator", L"Pass@12", ADS_SECURE_AUTHENTICATION, // 安全认证 IID_IADs, (void**)&pUsers); if (SUCCEEDED(hr)) { IDispatch* pDisp = NULL; CComBSTR sbstrName = "CN="; sbstrName += pwszName; // 在用户文件夹中创建新对象。 hr = pUsers->Create(CComBSTR("user"), sbstrName, &pDisp); if (SUCCEEDED(hr)) { IADsUser* padsUser = NULL; // 获取IADs接口。 // 我在此处遇到空指针异常。 hr = pDisp->QueryInterface(IID_IADsUser, (void**)&padsUser); if (SUCCEEDED(hr)) { CComBSTR sbstrProp; /* Windows Server 2003之前的操作系统要求sAMAccountName属性。 Windows Server 2003操作系统会在未指定时自动生成sAMAccountName值。 */ CComVariant svar; svar = pwszSAMAccountName; sbstrProp = "sAMAccountName"; hr = padsUser->Put(sbstrProp, svar); /* 将新用户提交到持久内存。 调用此方法前用户对象不存在。 */ hr = padsUser->SetInfo(); /* 设置初始密码。必须在调用SetInfo之后执行,因为用户对象必须已存在于服务器上。 */ hr = padsUser->SetPassword(CComBSTR(pwszInitialPassword)); /* 将pwdLastSet属性设置为0,强制用户下次登录时修改密码。 */ sbstrProp = "pwdLastSet"; svar = 0; hr = padsUser->Put(sbstrProp, svar); /* 通过从userAccountControl属性中移除ADS_UF_ACCOUNTDISABLE标志来启用用户账户。 同时移除ADS_UF_PASSWD_NOTREQD和ADS_UF_DONT_EXPIRE_PASSWD标志。 */ svar.Clear(); sbstrProp = "userAccountControl"; hr = padsUser->Get(sbstrProp, &svar); if (SUCCEEDED(hr)) { svar = svar.lVal & ~(ADS_UF_ACCOUNTDISABLE | ADS_UF_PASSWD_NOTREQD | ADS_UF_DONT_EXPIRE_PASSWD); hr = padsUser->Put(sbstrProp, svar); hr = padsUser->SetInfo(); } hr = padsUser->put_AccountDisabled(VARIANT_FALSE); hr = padsUser->SetInfo(); padsUser->Release(); } pDisp->Release(); } pUsers->Release(); } CoUninitialize(); return hr; }
排查与解决步骤
检查
Create方法的实际执行结果:
代码中仅通过SUCCEEDED(hr)判断Create成功,但部分场景下hr返回成功却未正确创建对象,导致pDisp为空。建议在Create调用后直接检查pDisp是否为空,同时输出hr的具体值,辅助定位问题:hr = pUsers->Create(CComBSTR("user"), sbstrName, &pDisp); if (SUCCEEDED(hr)) { if (!pDisp) { OutputDebugString(L"Create returned SUCCEEDED but pDisp is NULL\n"); } // 后续逻辑 } else { WCHAR errorMsg[256]; FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorMsg, ARRAYSIZE(errorMsg), NULL); OutputDebugStringW(errorMsg); }验证LDAP路径与账户权限:
- 确认LDAP连接字符串
LDAP://WIN-F94H2MP3UJR.Test.local/CN=Users,DC=Test,DC=local的正确性:域名、容器DN拼写无误,目标AD服务器可访问。 - 检查所用
Administrator账户的密码是否正确,且具备在CN=Users容器下创建用户的权限。可尝试手动用该账户登录ADUC创建用户,验证权限是否正常。
- 确认LDAP连接字符串
确保COM环境正确初始化:
CoInitialize(NULL)默认将线程初始化为单线程公寓(STA)模式,但ADSI严格要求STA环境。可改为CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)明确指定STA模式,避免环境不兼容问题。检查用户名合法性:
确保pwszName不含AD禁止的特殊字符(如逗号、双引号、斜杠等),避免因命名非法导致创建失败。
内容的提问来源于stack exchange,提问作者ironmanAJ
相关产品推荐
相关产品推荐

