You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建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创建用户,验证权限是否正常。
  • 确保COM环境正确初始化:
    CoInitialize(NULL)默认将线程初始化为单线程公寓(STA)模式,但ADSI严格要求STA环境。可改为CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)明确指定STA模式,避免环境不兼容问题。

  • 检查用户名合法性:
    确保pwszName不含AD禁止的特殊字符(如逗号、双引号、斜杠等),避免因命名非法导致创建失败。

内容的提问来源于stack exchange,提问作者ironmanAJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 08:00:29