将IntPtr解码为MultiString

本文关键字:MultiString 解码 IntPtr | 更新日期: 2023-09-27 18:17:44

我需要从对CreateEnvironmentBlock( out IntPtr lpEnvironment, IntPtr hToken, bool bInherit )的调用中提取环境字符串,以便根据变量名及其值将它们放入字典中。

当这个函数返回时,lpEnvironment接收到一个指向新的环境块。环境块是一个数组以空结尾的Unicode字符串。列表以两个空结束('0'0).

我不能轻易地使用Marshal.Copy,因为我不知道块的长度。我想知道是否有一个简单的方法来沿着它移动或确定什么复制到的东西,我可以更容易地转换。一种想法是将out IntPtr lpEnvironment作为out char [] lpEnvironment传递。

有什么建议吗?

将IntPtr解码为MultiString

您不知道Marshal.Copy()的整个长度,但是如果您执行Marshal.PtrToString(),您知道第一个字符串的长度。有了这些知识,你就可以进入下一个字符串,以此类推,直到你读到一个空字符串,这表明只有'0存在于该地址,这是多字符串的结尾。

请注意,下面的代码假设Unicode字符集可用并使用它。

[DllImport("userenv.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool CreateEnvironmentBlock(ref IntPtr lpEnvironment,IntPtr hToken,bool bInherit);
static IEnumerable<string> ExtractMultiString(IntPtr ptr)
{
    while (true)
    {
        string str = Marshal.PtrToStringUni(ptr);
        if (str.Length == 0)
            break;
        yield return str;
        ptr = new IntPtr(ptr.ToInt64() + (str.Length + 1 /* char '0 */) * sizeof(char));
    }
}