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

Windows Credential Providers V2 C# 多用户凭据显示问题求助

问题分析与解决方案

核心问题在于你使用**单个变量_pCredential**存储凭据实例,循环中每次创建新的CSharpSampleCredential都会覆盖之前的实例,最终系统只能识别到最后一个用户的凭据。要为每个用户生成独立凭据,需要用集合存储所有实例,并适配Windows凭据提供者的接口方法。

步骤1:替换单个变量为集合

在你的凭据提供者类中,将单个_pCredential变量替换为一个集合,用于存储所有用户的凭据:

// 替换原有的单个_pCredential变量
private List<ICredentialProviderCredential> _credentials = new List<ICredentialProviderCredential>();

步骤2:修改EnumerateCredentials方法

修改循环逻辑,将每个初始化成功的凭据添加到集合中,而不是覆盖单个变量:

int EnumerateCredentials()
{
    Log.LogMethodCall();
    int hr = HResultValues.E_UNEXPECTED;
    // 清空旧凭据集合
    _credentials.Clear();
    
    if (_pCredProviderUserArray != null)
    {
        uint dwUserCount = 0;
        _pCredProviderUserArray.GetCount(out dwUserCount);
        if (dwUserCount > 0)
        {
            for (uint i = 0; i < dwUserCount; i++)
            {
                ICredentialProviderUser pCredUser;
                hr = _pCredProviderUserArray.GetAt(i, out pCredUser);
                if (hr >= 0)
                {
                    var credential = new CSharpSampleCredential();
                    if (credential != null)
                    {
                        hr = credential.Initialize(_cpus, Field.s_rgCredProvFieldDescriptors, Field.s_rgFieldStatePairs, pCredUser);
                        if (hr >= 0)
                        {
                            // 初始化成功,将凭据加入集合
                            _credentials.Add(credential);
                        }
                        else
                        {
                            // 初始化失败,释放资源
                            var intPtr = Marshal.GetIUnknownForObject(credential);
                            Marshal.Release(intPtr);
                        }
                    }
                    else
                    {
                        hr = HResultValues.E_OUTOFMEMORY;
                    }
                    // 释放用户对象资源
                    var userPtr = Marshal.GetIUnknownForObject(pCredUser);
                    Marshal.Release(userPtr);
                }
                
                // 中途出错则终止循环
                if (hr < 0) break;
            }
            
            // 所有用户处理完成后返回成功状态
            if (hr >= 0) hr = HResultValues.S_OK;
        }
    }
    return hr;
}

步骤3:适配凭据提供者接口方法

需要修改GetCredentialCount和GetCredentialAt方法,让系统能从集合中获取所有凭据:

修改GetCredentialCount

int ICredentialProvider.GetCredentialCount(out uint pdwCount, out uint pdwDefault, out int pbAutoLogonWithDefault)
{
    pdwCount = (uint)_credentials.Count;
    pdwDefault = 0; // 设置默认选中的凭据索引(比如第一个用户)
    pbAutoLogonWithDefault = 0; // 关闭默认自动登录
    return HResultValues.S_OK;
}

修改GetCredentialAt

int ICredentialProvider.GetCredentialAt(uint dwIndex, out ICredentialProviderCredential ppCredential)
{
    ppCredential = null;
    // 索引超出范围返回错误
    if (dwIndex >= _credentials.Count)
        return HResultValues.E_INVALIDARG;
    
    ppCredential = _credentials[(int)dwIndex];
    return HResultValues.S_OK;
}

关键说明

  • 集合会保留每个用户对应的凭据实例,避免被覆盖
  • 接口方法通过索引从集合中取出对应凭据,让系统能显示所有用户的登录项
  • 注意资源释放:初始化失败的凭据要及时释放COM引用,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 14:40:45