Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the actual (localized) folder names? [duplicate]

I am writing a functionality in c# where I am required to list all the files/folder names in a given directory. The functionality runs fine on EN OS, but when I run the application on localized OS (for e.g.) German, I am still getting the English names of the Special Folders(Program Files instead of Programme, Favourites instead of Favoriten etc.). I don't think that Environment.GetFolderPath with Environment.SpecialFolder can be of any help as it does the exactly opposite of what I want i.e it gives the Full Path of the Special Folder enumerated, whereas, I want the localized name of the given path. I have tried using File, SHFileInfo, but of no use. Any idea, how can i get the folder names as displayed in the OS?

like image 420
Scotti Avatar asked Feb 28 '11 17:02

Scotti


People also ask

Can 2 folders have same name?

Because the operating system does not allow having two or more files with the same name in the same folder we will use a small trick.

Can we create two folders with the same name and the same location?

2 folders in the same folder cannot have the same name. The file system won't allow it. That you can manipulate the folders as you have also shows they are not identical.


2 Answers

You can get the localized display name with the 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; }
    }
}
like image 120
Thomas Levesque Avatar answered Oct 05 '22 08:10

Thomas Levesque


I did figure out how to get this to work. Not sure what's wrong with the above code (I also got Chinese Unicode characters), but this seems to work reliably. Just pass in the path (for example, by calling:

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

and it returns the display name of the folder (in this example, "My Documents" or whatever you've renamed it to).

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;
}
like image 41
Tom Clement Avatar answered Oct 05 '22 10:10

Tom Clement