如何获取本地化的特殊文件夹名称?

3
我使用SHGetFileInfo()或者GetDisplayNameOf()来获取一个特殊文件夹的名称。
如果本地化的操作系统更改了“非Unicode程序的当前语言”设置,这些函数会返回“??? ?????????” 的值。
这个设置组合较为常见。
shell32不完全支持Unicode吗?
Shell32.STRRET STRRET;
STRRET.uType = (uint)Shell32.STRRET_TYPE.STRRET_WSTR;
if (Windows.S_OK != ishellfolder_parent.GetDisplayNameOf(ptr_pidllast, (uint)Shell32.SHGNO.SHGDN_NORMAL | (uint)Shell32.SHGNO.SHGDN_INFOLDER, out STRRET))
                return null;

StringBuilder sbuilder = new StringBuilder(260);
Shell32.StrRetToBuf(ref STRRET, ptr_pidllast, sbuilder, (uint)sbuilder.Capacity);

有什么问题吗?

***稍后添加: 另一个示例以说明我的问题:

public static partial class Program
{
    const Int32 CSIDL_DESKTOP = (0x0000);
    const uint SHGFI_DISPLAYNAME = 0x000000200;     // get display name
    const uint SHGFI_PIDL = 0x000000008;     // pszPath is a pidl

    [StructLayout(LayoutKind.Sequential)]
    public struct SHFILEINFO
    {
        public static int NAMESIZE = 80;
        public IntPtr hIcon;
        public int iIcon;
        public uint dwAttributes;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string szDisplayName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
        public string szTypeName;
    };

    [DllImport("shell32.dll")]
    static extern IntPtr SHGetFileInfo(IntPtr pidl, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
    [DllImport("shell32.dll")]
    public static extern IntPtr SHCloneSpecialIDList(IntPtr hwnd, Int32 CSIDL, bool create);


    [STAThread]
    static void Main(string[] args)
    {
        IntPtr pidl = SHCloneSpecialIDList(IntPtr.Zero, CSIDL_DESKTOP, false);
        SHFILEINFO shfi = new SHFILEINFO();
        if (IntPtr.Zero != SHGetFileInfo(
                    pidl,
                    0,
                    ref shfi,
                    (uint)Marshal.SizeOf(typeof(SHFILEINFO)),
                    SHGFI_PIDL | SHGFI_DISPLAYNAME))
        {
            System.Windows.Forms.MessageBox.Show(shfi.szDisplayName);
        }

这段代码不正确。有些情况下会返回错误的值,如上所述。 有没有人能给我提供一个正确的代码示例,完全兼容Unicode并且可以在非默认系统设置下运行?


谢谢大家!经过一些尝试,我找到了解决方案。我的错误在于:

Shell32.StrRetToBuf(ref STRRET, ptr_pidllast, sbuilder, (uint)sbuilder.Capacity);

签名应该是:
[DllImport("shlwapi.dll", CharSet=CharSet.Unicode, EntryPoint="StrRetToBufW")]
public static extern Int32 StrRetToBufW( ...

尝试使用函数SHGetFileInfoW的unicode版本,然后GetDisplayNameOf应该返回类型为STRRET_WSTR的STRRET。 - Nathan Moinvaziri
谢谢回复。这是我尝试的第一件事。但它没有起作用。我在Windows 7、8上进行了检查。我在帖子中添加了代码示例之一。 - user1787509
你是如何进行测试的?你是将字符串写入控制台吗? - AbdElRaheim
你是在使用Shell32库,还是自己创建了一个包装P/Invoke签名的类?如果是后者,可以展示一下你正在使用的签名吗? - Damien_The_Unbeliever
1
与其在您的问题底部添加答案,您应该将其发布为答案(您是被允许的)。然后,您可以在适当的延迟后将其标记为已接受的答案,这将使那些稍后搜索的人更清楚地知道已找到答案。我注意到问题确实出现在P/Invoke签名中,但不是您发布的其中之一,所以我们没有太多帮助您的机会 :-( - Damien_The_Unbeliever
显示剩余2条评论
1个回答

1

如果您认为这个问题是重复的,您应该投票关闭并链接到该问题,而不是将其作为答案发布(我相信您有足够的声望来这样做 - 我认为您可以在250以上投票关闭)。 - Damien_The_Unbeliever
不,那对我来说不是一个选项 :( 那个选项通常在哪里出现? - AbdElRaheim
啊,抱歉。我误读了常见问题解答 - 你可以关闭自己的问题,但不能关闭别人的问题。不过,将其作为评论而不是答案仍然更好。 - Damien_The_Unbeliever
问题不是重复的,存在显著的差异。 - user1787509

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接