Estoy escribiendo una funcionalidad en C# donde estoy obligado a enumerar todos los nombres de archivos/carpetas en un directorio determinado. La funcionalidad funciona bien en EN OS, pero cuando ejecuto la aplicación en un sistema operativo localizado (por ejemplo) alemán, sigo recibiendo los nombres en inglés de las carpetas especiales (Archivos de programa en lugar de Program, Favorites en lugar de Favoriten, etc.). No creo que Environment.GetFolderPath con Environment.SpecialFolder puede ser de ninguna ayuda, ya que hace exactamente lo contrario de lo que quiero, es decir, da la ruta completa de la carpeta especial enumerada, mientras que, quiero el nombre localizado de la dada camino. He intentado usar File, SHFileInfo, pero no sirve de nada. Alguna idea, ¿cómo puedo obtener los nombres de las carpetas como se muestran en el sistema operativo?¿Cómo obtener los nombres de las carpetas reales (localizadas)?
Respuesta
Usted puede obtener el nombre de visualización localizada con la API SHGetFileInfo
:
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; }
}
}
exactamente lo que estaba buscando. Gracias. Sin embargo, tengo un problema más (no una regresión de este código, sino preexistente). Mientras hago una lista de los archivos, ahora obtengo dos archivos para el programa en alemán. Una es una carpeta y otra muestra como un enlace que en realidad es visible en el sistema operativo. Antes de realizar el cambio sugerido, obtenía el nombre no localizado para estas carpetas y el nombre localizado para los accesos directos. No quiero mostrar los accesos directos ya que hacen que la lista sea repetitiva. – Scotti
simplemente filtra los archivos .lnk –
obtengo '敄 歳 敄 p 敄' p' para 'Environment.SpecialFolder.Desktop' con culture' de-DE' (alemania). ¿Por qué? –
lo hice encontrar la manera de conseguir que esto funcione. No estoy seguro de lo que está mal con el código anterior (también obtuve caracteres chinos Unicode), pero parece que funciona de manera confiable. Sólo tiene que pasar en el camino (por ejemplo, llamando a:
GetDisplayName(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
y devuelve el nombre de visualización de la carpeta (en este ejemplo, "Mis documentos" o lo que sea que haya cambiado el nombre a)
.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;
}
Esto funciona en comparación con la otra solución que ofrece algunos caracteres chinos. – whywhywhy
Usted tiene que asegurarse de que CharSet se establece en Unicode para el DllImport y la StructLayout.
[DllImport("shell32", CharSet = CharSet.Unicode)]
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
- 1. Carpetas GAP IMAP localizadas
- 2. ¿Cómo cambiar los nombres de las carpetas en python?
- 3. ¿Carpetas reales en Visual Solution Explorer?
- 4. Obtener el nombre de las carpetas del directorio de Activos
- 5. ¿Cómo obtener los nombres de los archivos?
- 6. ¿Cómo puede obtener los nombres de los parámetros del método?
- 7. Obtener los valores reales de las variables de entorno en una máquina remota en .NET
- 8. ¿Hay alguna forma de obtener los nombres localizados de los botones de diálogo comunes?
- 9. ¿Cómo obtener los nombres de las hojas de los archivos XLS sin cargar todo el archivo?
- 10. NSFetchedResultsSecciones de controlador localizadas ordenadas
- 11. ¿Cómo obtener los nombres de las columnas junto con los resultados en php/mysql?
- 12. Obtener el tamaño total de las carpetas con find & du
- 13. ¿Debo usar '==' para las comparaciones de cadenas localizadas de .NET?
- 14. ¿Cómo obtener fotos reales de instagram en tiempo real?
- 15. ¿Cómo tratar los espacios en los nombres de las columnas?
- 16. ¿Cómo las personas eligen los nombres de los productos?
- 17. VB.NET: manteniendo los espacios de nombres de clase sincronizados con la estructura de carpetas
- 18. ¿Puedo obtener abreviaturas localizadas para los parámetros de tiempo con C# en ASP.NET?
- 19. ¿Cómo obtener todos los nombres de propiedades en una entidad?
- 20. ¿Cómo puedo obtener los nombres de las columnas y los datos de las filas en orden con DBI en Perl?
- 21. ¿Cómo incluir variables en cadenas localizadas?
- 22. ¿Cómo crear carpetas usando nombres de archivos y luego mover archivos a carpetas?
- 23. ¿Puede obtener acceso mediante programación a las cadenas localizadas estándar en Cocoa Touch?
- 24. Proguard mantener los nombres de las clases?
- 25. Cómo definir los nombres de las personas en texto (Java)
- 26. ¿Cómo obtener los argumentos de tipo reales para una interfaz genérica implementada indirectamente?
- 27. cómo obtener los nombres de las columnas de una tabla en ms access?
- 28. cómo obtener los nombres de las columnas de la clave principal para una tabla determinada?
- 29. cómo obtener todos los nombres de las tablas en la base de datos sqlCE?
- 30. Cómo NO incluir nombres de carpetas de Visual Studio Project en espacios de nombres generados
creo que u necesidad de establecer la configuración regional en el código ... –
diría el nombre Inglés es el nombre real (lo necesitas) para acceder al archivo) y el nombre alemán es solo el nombre para mostrar. – CodesInChaos