using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Runtime.InteropServices; namespace Developpez.Dotnet.System { /// /// Utilitaires pour la gestion des fichiers /// public static class FileUtils { /// /// Combine les chemins passés en paramètre /// /// Chemins /// Chemins combinés (indépendant de la plateforme) public static string CombinePaths(params string[] paths) { if (paths == null || paths.Length < 1) return String.Empty; else { string result = paths[0]; if (paths.Length > 0) { for (int i = 1; i < paths.Length; i++) { result = Path.Combine(result, paths[i]); } } return result; } } /// /// Transforme un chemin absolu en un chemin relatif au répertoire de base spécifié /// /// Chemin absolu à transformer /// Chemin du répertoire de base /// Un chemin relatif au répertoire de base public static string MakeRelativePath(string path, string basePath) { if (basePath.LastOrDefault() != Path.DirectorySeparatorChar) basePath += Path.DirectorySeparatorChar; Uri pathUri = new Uri(path); Uri baseUri = new Uri(basePath); return baseUri .MakeRelativeUri(pathUri) .ToString() .Replace('/', Path.DirectorySeparatorChar); } /// /// Recherche des fichiers de manière récursive dans le dossier baseDirectory en utilisant predicate afin de sélectionner ou non un fichier. /// cancelHandler sert à déterminer si la recherche doit se poursuivre ou être interrompue /// /// Dossier à partir duquel commencer la recherche /// Prédicat à utiliser pour sélectionner des fichiers /// Indicateur d'annulation (peut être null) /// Liste des fichiers sélectionnées durant la recherche public static FileInfo[] FindFiles(DirectoryInfo baseDirectory, Predicate predicate, CancelEventHandler cancelHandler) { List result = new List(); Queue work = new Queue(); /* Pour éviter les StackOverflow par la récursivité */ work.Enqueue(baseDirectory); CancelEventArgs c_args = new CancelEventArgs(); c_args.Cancel = false; DirectoryInfo workingDirectory = null; while (work.Count > 0) { if (cancelHandler != null) { cancelHandler.Invoke(null, c_args); if (c_args.Cancel) break; } /* il est même possible de séparer tout ça entre plusieurs threads */ workingDirectory = work.Dequeue(); try { FileInfo[] files = workingDirectory.GetFiles(); if (predicate == null) result.AddRange(files); else { foreach (FileInfo file in files) { if (predicate.Invoke(file)) result.Add(file); } } foreach (DirectoryInfo sub_dir in workingDirectory.GetDirectories()) { work.Enqueue(sub_dir); } } catch (IOException) { /* on ignore */ } catch (UnauthorizedAccessException) { /* on ignore aussi */ } } return result.ToArray(); } /// /// Renvoie la description du type de fichier correspondant au nom de fichier /// ou à l'extension passée en paramètre /// /// Nom de fichier ou extension /// La description du type de fichier, telle qu'affichée dans l'explorateur Windows public static string GetFileTypeDescription(string fileNameOrExtension) { SHFILEINFO shfi; if (0 != SHGetFileInfo( fileNameOrExtension, FILE_ATTRIBUTE_NORMAL, out shfi, (uint)Marshal.SizeOf(typeof(SHFILEINFO)), SHGFI_USEFILEATTRIBUTES | SHGFI_TYPENAME)) { return shfi.szTypeName; } return null; } /// /// Renvoie le nom d'un fichier ou répertoire, tel qu'affiché dans l'explorateur Windows /// /// Chemin du fichier ou répertoire /// Nom d'affichage du fichier ou répertoire 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; } /// /// Renvoie le nom d'un répertoire spécial du système, tel qu'affiché dans l'explorateur Windows /// /// L'identifiant du répertoire spécial /// Le nom d'affichage du répertoire spécial 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); } } #region Interop declarations [DllImport("shell32")] private static extern int SHGetFileInfo(string pszPath, uint dwFileAttributes, out SHFILEINFO psfi, uint cbFileInfo, uint flags); [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)] 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; } private const uint FILE_ATTRIBUTE_READONLY = 0x00000001; private const uint FILE_ATTRIBUTE_HIDDEN = 0x00000002; private const uint FILE_ATTRIBUTE_SYSTEM = 0x00000004; private const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010; private const uint FILE_ATTRIBUTE_ARCHIVE = 0x00000020; private const uint FILE_ATTRIBUTE_DEVICE = 0x00000040; private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080; private const uint FILE_ATTRIBUTE_TEMPORARY = 0x00000100; private const uint FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200; private const uint FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400; private const uint FILE_ATTRIBUTE_COMPRESSED = 0x00000800; private const uint FILE_ATTRIBUTE_OFFLINE = 0x00001000; private const uint FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000; private const uint FILE_ATTRIBUTE_ENCRYPTED = 0x00004000; private const uint FILE_ATTRIBUTE_VIRTUAL = 0x00010000; private const uint SHGFI_ICON = 0x000000100; // get icon private const uint SHGFI_DISPLAYNAME = 0x000000200; // get display name private const uint SHGFI_TYPENAME = 0x000000400; // get type name private const uint SHGFI_ATTRIBUTES = 0x000000800; // get attributes private const uint SHGFI_ICONLOCATION = 0x000001000; // get icon location private const uint SHGFI_EXETYPE = 0x000002000; // return exe type private const uint SHGFI_SYSICONINDEX = 0x000004000; // get system icon index private const uint SHGFI_LINKOVERLAY = 0x000008000; // put a link overlay on icon private const uint SHGFI_SELECTED = 0x000010000; // show icon in selected state private const uint SHGFI_ATTR_SPECIFIED = 0x000020000; // get only specified attributes private const uint SHGFI_LARGEICON = 0x000000000; // get large icon private const uint SHGFI_SMALLICON = 0x000000001; // get small icon private const uint SHGFI_OPENICON = 0x000000002; // get open icon private const uint SHGFI_SHELLICONSIZE = 0x000000004; // get shell size icon private const uint SHGFI_PIDL = 0x000000008; // pszPath is a pidl private const uint SHGFI_USEFILEATTRIBUTES = 0x000000010; // use passed dwFileAttribute #endregion } }