使用CredentialCache存储RDP凭证失败,求技术解决方案
问题分析
你用CredentialCache类的思路从根上错了——这个类是用来给当前.NET应用内部缓存网络请求凭证的,根本不会把凭证写入Windows系统的「凭证管理器」。代码没报错只是因为语法合法,但完全没触及系统凭证存储的逻辑。
另外你最初尝试的TERMSRV//RemoteMachine格式,其实是Windows凭证管理器中RDP凭证的目标名称格式,但CredentialCache的Uri参数不支持这种格式,所以会报错。
正确实现方式
要把RDP凭证写入系统凭证管理器,需要调用Windows原生的凭据管理API,下面提供两种可行方案:
方案1:直接使用P/Invoke调用Windows API
不需要额外依赖,直接通过平台调用实现:
using System; using System.Runtime.InteropServices; public class RdpCredentialManager { // 定义Windows凭据API所需的结构体和常量 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct CREDENTIAL { public int Flags; public int Type; public string TargetName; public string Comment; public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten; public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist; public int AttributeCount; public IntPtr Attributes; public string TargetAlias; public string UserName; } [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern bool CredWrite([In] ref CREDENTIAL credential, [In] int flags); /// <summary> /// 写入RDP凭证到系统凭证管理器 /// </summary> /// <param name="remoteMachine">远程机器名/IP</param> /// <param name="username">用户名(格式:domain\user 或 user)</param> /// <param name="password">密码</param> /// <returns>是否成功</returns> public static bool AddRdpCredential(string remoteMachine, string username, string password) { var credential = new CREDENTIAL { Type = 1, // CRED_TYPE_GENERIC TargetName = $"TERMSRV/{remoteMachine}", // RDP凭证的目标名称固定以TERMSRV/开头 UserName = username, Persist = 2, // CRED_PERSIST_LOCAL:本地持久化,重启后保留 CredentialBlobSize = password.Length * 2, CredentialBlob = Marshal.StringToHGlobalUni(password) }; bool result = CredWrite(ref credential, 0); Marshal.FreeHGlobal(credential.CredentialBlob); // 释放非托管内存 return result; } } // 使用示例 // RdpCredentialManager.AddRdpCredential("RemoteMachine", @"domain\username", "password");
方案2:使用第三方NuGet包简化操作
如果不想写复杂的P/Invoke代码,可以使用CredentialManagement这个NuGet包:
- 安装NuGet包:
Install-Package CredentialManagement - 编写代码:
using CredentialManagement; // 写入RDP凭证 using (var credential = new Credential()) { credential.Target = $"TERMSRV/RemoteMachine"; credential.Username = @"domain\username"; credential.Password = "password"; credential.Type = CredentialType.Generic; credential.PersistanceType = PersistanceType.LocalComputer; credential.Save(); }
关键注意事项
- RDP凭证在系统凭证管理器中的目标名称必须是
TERMSRV/[远程机器名/IP],这是Windows的固定规则 - 普通本地凭证写入不需要管理员权限,若写入企业级凭证可能需要对应权限
- 验证写入结果可打开「控制面板→用户账户→凭据管理器→Windows凭据」查看
内容的提问来源于stack exchange,提问作者Iunknown
相关产品推荐
相关产品推荐

