C# 使用SecureString从.NET获取凭据的CredUIPromptForCredentials

C# 使用SecureString从.NET获取凭据的CredUIPromptForCredentials,c#,pinvoke,securestring,C#,Pinvoke,Securestring,我想显示标准系统对话框,要求用户输入帐户用户名和密码,以使用此信息启动具有这些凭据的进程 我被指向显示该对话框的CredUIPromptForCredentials函数。它以字符串形式返回用户名和密码。但是ProcessStartInfo结构要求密码为SecureString 我知道我现在可以将密码作为字符串使用,并将其逐字符转换为SecureString(没有单独的函数),但这将彻底挫败SecureString背后的想法 因此,我想一定有某种方法可以直接从.NET中对CredUIPromptF

我想显示标准系统对话框,要求用户输入帐户用户名和密码,以使用此信息启动具有这些凭据的进程

我被指向显示该对话框的
CredUIPromptForCredentials
函数。它以字符串形式返回用户名和密码。但是
ProcessStartInfo
结构要求密码为
SecureString

我知道我现在可以将密码作为字符串使用,并将其逐字符转换为
SecureString
(没有单独的函数),但这将彻底挫败
SecureString
背后的想法

因此,我想一定有某种方法可以直接从.NET中对
CredUIPromptForCredentials
as
SecureString
的非托管调用中接受密码。毕竟,我真的不需要以任何方式访问应用程序中的密码。它只是用来开始另一个过程,然后可以尽快忘记

那么,我的
CredUIPromptForCredentials
的p/Invoke声明与
SecureString
是什么样的呢?(我从C#的pinvoke.net开始)


更新:哦,如果有人在Windows Vista/7中有一个新功能
CredUIPromptForWindowsCredentials
的例子,那也很酷,因为我现在甚至不知道如何使用它。

您可以将非托管字符串缓冲区的
IntPtr
强制转换为
char*
,并使用
SecureString(char*,int)
构造函数

// somehow, we come into posession of an IntPtr to a string
// obviously, this would be a foolish way to come into it in
// production, since stringOriginalContents is already in managed
// code, and the lifetime can therefore not be guaranteed...
var stringOriginalContents = "foobar";
IntPtr strPtr = Marshal.StringToHGlobalUni(stringOriginalContents);
int strLen = stringOriginalContents.Length;
int maxLen = 100;

// we copy the IntPtr to a SecureString, and zero out the old location
SecureString ssNew;
unsafe
{
    char* strUPtr = (char*)strPtr;

    // if we don't know the length, calculate
    //for (strLen = 0; *(strUPtr + strLen) != '\0' 
    //    // stop if the string is invalid
    //    && strLen < maxLen; strLen++)
    //    ;

    ssNew = new SecureString((char*)strPtr, strLen);

    // zero out the old memory and release, or use a Zero Free method
    //for (int i = 0; i < strLen; i++)
    //    *(strUPtr + i) = '\0';
    //Marshal.FreeHGlobal(strPtr);
    // (only do one of these)
    Marshal.ZeroFreeGlobalAllocUnicode(strPtr);
}

// now the securestring has the protected data, and the old memory has been
// zeroed, we can check that the securestring is correct.  This, also should
// not be in production code.
string strInSecureString =
    Marshal.PtrToStringUni(
    Marshal.SecureStringToGlobalAllocUnicode(ssNew));
Assert.AreEqual(strInSecureString, stringOriginalContents);
//不知何故,我们将IntPtr转换为字符串
//显然,这将是一个愚蠢的方式来进入它的
//生产,因为Stringoriginal内容已经在管理中
//代码,因此无法保证使用寿命。。。
var stringOriginalContents=“foobar”;
IntPtr strPtr=Marshal.StringToHGlobalUni(stringOriginalContents);
int strLen=stringOriginalContents.Length;
int maxLen=100;
//我们将IntPtr复制到SecureString,并将旧位置归零
安全字符串ssNew;
不安全的
{
char*strUPtr=(char*)strprtr;
//如果我们不知道长度,计算一下
//对于(strLen=0;*(strUPtr+strLen)!='\0'
////如果字符串无效,则停止
//&&strLen