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

C#自定义Credential Provider开发:控件取值与弹窗问题咨询

自定义Windows Credential Provider问题解决

问题1:点击命令按钮时无法读取文本框的值

Windows Credential Provider的控件交互模型由系统负责同步控件值到你的Credential实例,而非直接读取控件。解决步骤如下:

  1. 在实现ICredentialProviderCredential的自定义Credential类中,为每个编辑框声明成员变量存储值:
private:
    std::wstring m_szUsername;
    std::wstring m_szPassword;
  1. 重写SetStringValue方法,当系统传递控件字段ID时,将对应值保存到成员变量:
HRESULT STDMETHODCALLTYPE YourCredential::SetStringValue(DWORD dwFieldID, PCWSTR pszValue)
{
    HRESULT hr = S_OK;
    switch (dwFieldID)
    {
        case FIELD_USERNAME: // 替换为你定义的用户名字段ID
            m_szUsername = pszValue;
            break;
        case FIELD_PASSWORD: // 替换为你定义的密码字段ID
            m_szPassword = pszValue;
            break;
        default:
            hr = E_INVALIDARG;
            break;
    }
    return hr;
}
  1. 在命令按钮的处理方法OnUserCommand中,直接使用保存的成员变量即可:
HRESULT STDMETHODCALLTYPE YourCredential::OnUserCommand(DWORD dwFieldID, DWORD dwUserCommandID)
{
    if (dwUserCommandID == CMD_TRIGGER_MFA) // 替换为你的命令按钮ID
    {
        // 直接调用已保存的文本框值
        std::wstring username = m_szUsername;
        // 后续业务逻辑
        return S_OK;
    }
    return E_INVALIDARG;
}

问题2:打开自定义MFA窗体

登录UI运行在Winlogon安全桌面,普通窗体无法直接显示,需按以下步骤实现:

  1. 准备独立的MFA窗体程序:

    • 编写基础Win32窗体程序,避免使用依赖用户桌面的特性(如透明效果)
    • 添加应用程序清单,设置requestedExecutionLevel为highestAvailable,确保程序能在安全桌面启动
  2. 在Credential类的OnUserCommand方法中,切换到安全桌面并启动MFA进程:

HRESULT STDMETHODCALLTYPE YourCredential::OnUserCommand(DWORD dwFieldID, DWORD dwUserCommandID)
{
    if (dwUserCommandID == CMD_TRIGGER_MFA)
    {
        HDESK hWinlogonDesktop = OpenDesktop(L"Winlogon", 0, FALSE, GENERIC_ALL);
        if (!hWinlogonDesktop)
            return HRESULT_FROM_WIN32(GetLastError());

        HDESK hOldDesktop = GetThreadDesktop(GetCurrentThreadId());
        SetThreadDesktop(hWinlogonDesktop);

        // 构造启动参数,传递用户名等信息
        std::wstring cmdLine = L"YourMFA.exe /user:" + m_szUsername;
        STARTUPINFO si = { sizeof(STARTUPINFO) };
        PROCESS_INFORMATION pi = { 0 };

        // 启动MFA进程
        BOOL success = CreateProcessAsUser(
            NULL,
            NULL,
            const_cast<LPWSTR>(cmdLine.c_str()),
            NULL,
            NULL,
            FALSE,
            0,
            NULL,
            NULL,
            &si,
            &pi
        );

        if (success)
        {
            // 等待MFA窗体关闭
            WaitForSingleObject(pi.hProcess, INFINITE);
            
            DWORD exitCode = 0;
            GetExitCodeProcess(pi.hProcess, &exitCode);
            
            // 根据MFA验证结果更新登录UI状态
            if (exitCode == 0) // 假设0表示验证成功
            {
                m_pCredentialProviderEvents->SetFieldState(this, FIELD_SUBMIT, CPFS_VALID);
            }
            else
            {
                m_pCredentialProviderEvents->SetFieldState(this, FIELD_SUBMIT, CPFS_INVALID);
            }

            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
        }

        // 切换回原桌面并释放资源
        SetThreadDesktop(hOldDesktop);
        CloseDesktop(hWinlogonDesktop);

        return S_OK;
    }
    return E_INVALIDARG;
}
  1. 注意事项:
    • MFA程序需处理命令行参数,接收用户名等信息
    • 安全桌面下部分系统API无法使用,需测试窗体兼容性
    • 验证完成后,需通过ICredentialProviderEvents通知登录UI更新控件状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 21:30:45