如何获取实际(本地化)文件夹名称?

时间:2011-02-28 17:33:01

标签: c# file internationalization system

我正在c#中编写一个功能,我需要列出给定目录中的所有文件/文件夹名称。该功能在EN OS上运行良好,但是当我在本地化操作系统(例如德语)上运行应用程序时,我仍然获得特殊文件夹的英文名称(程序文件而不是程序,收藏夹而不是收藏夹等)。我不认为带有Environment.SpecialFolder的Environment.GetFolderPath可以提供任何帮助,因为它与我想要的完全相反,即它给出了枚举的特殊文件夹的完整路径,而我想要给定的本地化名称路径。我曾尝试使用File,SHFileInfo,但没有用。任何想法,我如何获得操作系统中显示的文件夹名称?

3 个答案:

答案 0 :(得分:12)

您可以使用SHGetFileInfo API获取本地化的显示名称:

    public  static string GetDisplayName(Environment.SpecialFolder specialFolder)
    {
        IntPtr pidl = IntPtr.Zero;
        try
        {
            HResult hr = SHGetFolderLocation(IntPtr.Zero, (int) specialFolder, IntPtr.Zero, 0, out pidl);
            if (hr.IsFailure)
                return null;

            SHFILEINFO shfi;
            if (0 != SHGetFileInfo(
                        pidl,
                        FILE_ATTRIBUTE_NORMAL,
                        out shfi,
                        (uint)Marshal.SizeOf(typeof(SHFILEINFO)),
                        SHGFI_PIDL | SHGFI_DISPLAYNAME))
            {
                return shfi.szDisplayName;
            }
            return null;
        }
        finally
        {
            if (pidl != IntPtr.Zero)
                ILFree(pidl);
        }
    }

    public static string GetDisplayName(string path)
    {
        SHFILEINFO shfi;
        if (0 != SHGetFileInfo(
                    path,
                    FILE_ATTRIBUTE_NORMAL,
                    out shfi,
                    (uint)Marshal.SizeOf(typeof(SHFILEINFO)),
                    SHGFI_DISPLAYNAME))
        {
            return shfi.szDisplayName;
        }
        return null;
    }

    private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
    private const uint SHGFI_DISPLAYNAME = 0x000000200;     // get display name
    private const uint SHGFI_PIDL = 0x000000008;     // pszPath is a pidl

    [DllImport("shell32")]
    private static extern int SHGetFileInfo(IntPtr pidl, uint dwFileAttributes, out SHFILEINFO psfi, uint cbFileInfo, uint flags);
    [DllImport("shell32")]
    private static extern HResult SHGetFolderLocation(IntPtr hwnd, int nFolder, IntPtr token, int dwReserved, out IntPtr pidl);
    [DllImport("shell32")]
    private static extern void ILFree(IntPtr pidl);

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
    private struct SHFILEINFO
    {
        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;
    }

[StructLayout(LayoutKind.Sequential)]
public struct HResult
{
    private int _value;

    public int Value
    {
        get { return _value; }
    }

    public Exception Exception
    {
        get { return Marshal.GetExceptionForHR(_value); }
    }

    public bool IsSuccess
    {
        get { return _value >= 0; }
    }

    public bool IsFailure
    {
        get { return _value < 0; }
    }
}

答案 1 :(得分:4)

我确实弄明白了如何让它发挥作用。不确定上面代码有什么问题(我也有中文Unicode字符),但这似乎可靠。只需传入路径(例如,通过调用:

GetDisplayName(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));

并返回文件夹的显示名称(在本例中为“我的文档”或您重命名为的任何内容)。

using System.Runtime.InteropServices;
...
public const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
public const uint SHGFI_DISPLAYNAME = 0x000000200;     // get display name

[DllImport("shell32")]
public static extern int SHGetFileInfo(string pszPath, uint dwFileAttributes, 
    out SHFILEINFO psfi, uint cbFileInfo, uint flags);

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


public  static string GetDisplayName(string path)
{
    SHFILEINFO shfi = new SHFILEINFO();
    if (0 != SHGetFileInfo(path,FILE_ATTRIBUTE_NORMAL,out shfi,
        (uint)Marshal.SizeOf(typeof(SHFILEINFO)),SHGFI_DISPLAYNAME))
    {
        return shfi.szDisplayName;
    }
    return null;
}

答案 2 :(得分:0)

您必须确保将CharSet设置为DllImport和StructLayout的UniCode。

[DllImport("shell32", CharSet = CharSet.Unicode)]
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
相关问题