How to get the actual (localized) folder names?

I am writing functionality in C # where I need to list all the file / folder names in a given directory. The functionality works fine in EN OS, but when I run the application on a localized OS (for example, in German), I still get the English names of special folders (Program Files instead of Program, Favorites instead of Favoriten, etc.). I don't think Environment.GetFolderPath with Environment.SpecialFolder can be of any help, since it is exactly the opposite of what I want, i.e. it gives the full path to the special folder, but I want the localized name of the given track. I tried using File, SHFileInfo, but to no avail. Any idea how I can get the folder names displayed in the OS?

+6
c # file internationalization system
source share
3 answers

You can get the localized display name using 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; } } } 
+11
source share

I figured out how to make this work. Not sure whats wrong with the above code (I also got Chinese Unicode characters), but this seems to work reliably. Just follow the path (e.g. 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 renamed 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; } 
+2
source share

You must ensure that CharSet is set to UniCode for DllImport and StructLayout.

 [DllImport("shell32", CharSet = CharSet.Unicode)] [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] 
0
source share

All Articles