Created
May 9, 2017 15:57
-
-
Save soeminnminn/aec9de809ed39c4f380926940da5d769 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Text; | |
using System.IO; | |
using System.Runtime.ConstrainedExecution; | |
using System.Runtime.InteropServices; | |
using System.Security.Permissions; | |
namespace S16.IO | |
{ | |
#region FilesList Class | |
public class FilesList : IEnumerable<PathInfo> | |
{ | |
#region API Methods | |
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)] | |
private static extern SafeFileHandle FindFirstFile(String fileName, [In, Out] WIN32_FIND_DATA findFileData); | |
[DllImport("kernel32", CharSet = CharSet.Auto)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool FindNextFile(SafeFileHandle hFindFile, [In, Out] WIN32_FIND_DATA lpFindFileData); | |
[DllImport("kernel32", CharSet = CharSet.Auto)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool FindClose(IntPtr hFindFile); | |
#endregion | |
#region Variables | |
private string mBasePath = null; | |
private string mMask = null; | |
private bool mWithSubFolder = false; | |
#endregion | |
#region Constructor | |
public FilesList(string basePath, string mask, bool bWithSubFolder) | |
{ | |
if (string.IsNullOrEmpty(basePath)) | |
{ | |
throw new ArgumentNullException("basePath"); | |
} | |
this.mBasePath = basePath; | |
this.mMask = string.IsNullOrEmpty(mask) ? "*" : mask; | |
this.mWithSubFolder = bWithSubFolder; | |
} | |
#endregion | |
#region GetFliesList Methods | |
public static string[] GetFliesList(string path) | |
{ | |
return GetFliesList(path, "*.*", false, false); | |
} | |
public static string[] GetFliesList(string path, string mask) | |
{ | |
return GetFliesList(path, mask, false, false); | |
} | |
public static string[] GetFliesList(string path, string mask, bool bWithSubFolder) | |
{ | |
return GetFliesList(path, mask, bWithSubFolder, false); | |
} | |
public static string[] GetFliesList(string path, string mask, bool bWithSubFolder, bool bWithFolderName) | |
{ | |
string basePath = path.Trim(); | |
List<string> list = new List<string>(); | |
GetFilesList(path, mask, bWithSubFolder, bWithFolderName, ref list); | |
return list.ToArray(); | |
} | |
#endregion | |
#region GetFliesList Internal Methods | |
internal static void GetFilesList(string basePath, string mask, bool bWithSubFolder, bool bWithFolderName, ref List<string> list) | |
{ | |
// check security - ensure that caller has rights to read this directory | |
new FileIOPermission(FileIOPermissionAccess.PathDiscovery, Path.Combine(basePath, ".")).Demand(); | |
// now that security is checked, go read the directory | |
WIN32_FIND_DATA findData = new WIN32_FIND_DATA(); | |
SafeFileHandle handle = FindFirstFile(Path.Combine(basePath, mask), findData); | |
if (!handle.IsInvalid) | |
{ | |
do | |
{ | |
// don't match . or .. | |
if (findData.fileName.Equals(@".") || findData.fileName.Equals(@"..")) | |
continue; | |
if ((findData.fileAttributes & (int)FileAttributes.Directory) != 0) | |
{ | |
if (bWithSubFolder) | |
{ | |
// it's a directory - recurse into it | |
GetFilesList(Path.Combine(basePath, findData.fileName), mask, bWithSubFolder, bWithFolderName, ref list); | |
} | |
} | |
else | |
{ | |
string filePath = (bWithFolderName ? Path.Combine(basePath, findData.fileName) : findData.fileName); | |
list.Add(filePath); | |
} | |
} while (FindNextFile(handle, findData)); | |
// close this find handle | |
handle.Close(); | |
} | |
} | |
#endregion | |
#region Methods | |
public IEnumerator<PathInfo> GetEnumerator() | |
{ | |
return new FilesListEnumerator(this.mBasePath, this.mMask, this.mWithSubFolder); | |
} | |
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() | |
{ | |
return this.GetEnumerator(); | |
} | |
#endregion | |
#region Nested Types | |
#region FilesListEnumerator Class | |
public class FilesListEnumerator : IEnumerator<PathInfo> | |
{ | |
#region Variables | |
private string mBasePath = null; | |
private string mMask = null; | |
private bool mWithSubFolder = false; | |
private string mCurrentPath = null; | |
private SafeFileHandle mHandle = null; | |
private PathInfo mCurrent = null; | |
private Queue<string> mQueue = null; | |
#endregion | |
#region Constructor | |
public FilesListEnumerator(string basePath, string mask, bool bWithSubFolder) | |
{ | |
if (string.IsNullOrEmpty(basePath)) | |
{ | |
throw new ArgumentNullException("basePath"); | |
} | |
this.mBasePath = basePath; | |
this.mMask = string.IsNullOrEmpty(mask) ? "*" : mask; | |
this.mWithSubFolder = bWithSubFolder; | |
this.mQueue = new Queue<string>(); | |
this.mCurrentPath = this.mBasePath; | |
} | |
#endregion | |
#region Methods | |
public void Dispose() | |
{ | |
if (this.mHandle != null) | |
{ | |
this.mHandle.Close(); | |
this.mHandle = null; | |
} | |
} | |
public bool MoveNext() | |
{ | |
if (string.IsNullOrEmpty(this.mCurrentPath)) return false; | |
new FileIOPermission(FileIOPermissionAccess.PathDiscovery, Path.Combine(this.mCurrentPath, ".")).Demand(); | |
bool result = false; | |
WIN32_FIND_DATA findData = new WIN32_FIND_DATA(); | |
if (this.mHandle == null) | |
{ | |
SafeFileHandle handle = FindFirstFile(Path.Combine(this.mCurrentPath, this.mMask), findData); | |
if ((handle != null) && (!handle.IsInvalid)) | |
{ | |
result = true; | |
while (findData.fileName.Equals(@".") || findData.fileName.Equals(@"..")) | |
{ | |
result = FindNextFile(handle, findData); | |
if (!result) break; | |
} | |
this.mHandle = handle; | |
} | |
} | |
else | |
{ | |
result = FindNextFile(this.mHandle, findData); | |
} | |
if (result) | |
{ | |
string filePath = Path.Combine(this.mCurrentPath, findData.fileName); | |
if ((findData.fileAttributes & (int)FileAttributes.Directory) != 0) | |
{ | |
this.mQueue.Enqueue(filePath); | |
} | |
else | |
{ | |
this.mCurrent = new PathInfo(filePath); | |
//System.Diagnostics.Trace.WriteLine(filePath); | |
} | |
} | |
else | |
{ | |
if (this.mHandle != null) | |
{ | |
this.mHandle.Close(); | |
this.mHandle = null; | |
} | |
if (this.mQueue.Count > 0) | |
{ | |
this.mCurrentPath = this.mQueue.Dequeue(); | |
result = this.MoveNext(); | |
} | |
} | |
return result; | |
} | |
public void Reset() | |
{ | |
this.mQueue.Clear(); | |
if (this.mHandle != null) | |
{ | |
this.mHandle.Close(); | |
this.mHandle = null; | |
} | |
this.mCurrent = null; | |
this.mCurrentPath = this.mBasePath; | |
} | |
#endregion | |
#region Properties | |
public PathInfo Current | |
{ | |
get { return this.mCurrent; } | |
} | |
object System.Collections.IEnumerator.Current | |
{ | |
get { return this.Current; } | |
} | |
#endregion | |
} | |
#endregion | |
#region WIN32_FIND_DATA Class | |
/// <summary> | |
/// Structure that maps to WIN32_FIND_DATA | |
/// </summary> | |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto), BestFitMapping(false)] | |
internal sealed class WIN32_FIND_DATA | |
{ | |
public int fileAttributes; | |
public uint creationTime_lowDateTime; | |
public uint creationTime_highDateTime; | |
public uint lastAccessTime_lowDateTime; | |
public uint lastAccessTime_highDateTime; | |
public uint lastWriteTime_lowDateTime; | |
public uint lastWriteTime_highDateTime; | |
public uint nFileSizeHigh; | |
public uint nFileSizeLow; | |
public int dwReserved0; | |
public int dwReserved1; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] | |
public string fileName; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] | |
public string alternateFileName; | |
} | |
#endregion | |
#region SafeFileHandle Class | |
/// <summary> | |
/// SafeHandle class for holding find handles | |
/// </summary> | |
private sealed class SafeFileHandle : Microsoft.Win32.SafeHandles.SafeHandleMinusOneIsInvalid | |
{ | |
/// <summary> | |
/// Constructor | |
/// </summary> | |
public SafeFileHandle() | |
: base(true) | |
{ | |
} | |
/// <summary> | |
/// Release the find handle | |
/// </summary> | |
/// <returns>true if the handle was released</returns> | |
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] | |
protected override bool ReleaseHandle() | |
{ | |
return FindClose(handle); | |
} | |
} | |
#endregion | |
#endregion | |
} | |
#endregion | |
#region PathInfo Class | |
public class PathInfo | |
{ | |
#region API Methods | |
[DllImport("shell32.dll", CharSet = CharSet.Auto)] | |
private static extern int SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags); | |
#endregion | |
#region Constant | |
private const uint SHGFI_DISPLAYNAME = 0x200; | |
private const uint SHGFI_ICON = 0x100; | |
private const uint SHGFI_LINKOVERLAY = 0x8000; | |
private const uint SHGFI_SELECTED = 0x10000; | |
private const uint SHGFI_SYSICONINDEX = 0x4000; | |
private const uint SHGFI_TYPENAME = 0x400; | |
#endregion | |
#region Variables | |
private string mFilePath = ""; | |
private bool mLargeIcon = false; | |
private bool mLinkOverlay = false; | |
private bool mSelected = false; | |
private DateTime mCreationTime = DateTime.Now; | |
private DateTime mLastAccesTime = DateTime.Now; | |
private DateTime mLastWriteTime = DateTime.Now; | |
private long mLength = 0L; | |
private FileAttributes mAttributes = FileAttributes.Normal; | |
private string mFileName = null; | |
private string mAlternateFileName = null; | |
#endregion | |
#region Constructor | |
public PathInfo() | |
{ | |
} | |
public PathInfo(string filePath) | |
: this() | |
{ | |
this.mFilePath = filePath; | |
if (!string.IsNullOrEmpty(filePath)) | |
{ | |
FileInfo fileInfo = new FileInfo(filePath); | |
this.mFileName = fileInfo.Name; | |
this.mAttributes = fileInfo.Attributes; | |
this.mCreationTime = fileInfo.CreationTime; | |
this.mLastAccesTime = fileInfo.LastAccessTime; | |
this.mLastWriteTime = fileInfo.LastWriteTime; | |
this.mLength = fileInfo.Length; | |
} | |
} | |
internal PathInfo(string filePath, FilesList.WIN32_FIND_DATA findData) | |
{ | |
this.mFilePath = filePath; | |
if (findData != null) | |
{ | |
this.mAttributes = (FileAttributes)findData.fileAttributes; | |
this.mCreationTime = ConvertDateTime(findData.creationTime_highDateTime, findData.creationTime_lowDateTime); | |
this.mLastAccesTime = ConvertDateTime(findData.lastAccessTime_highDateTime, findData.lastAccessTime_lowDateTime); | |
this.mLastWriteTime = ConvertDateTime(findData.lastWriteTime_highDateTime, findData.lastWriteTime_lowDateTime); | |
this.mLength = CombineHighLowInts(findData.nFileSizeHigh, findData.nFileSizeLow); | |
this.mAlternateFileName = findData.alternateFileName; | |
} | |
} | |
#endregion | |
#region Methods | |
public override bool Equals(object obj) | |
{ | |
if (!string.IsNullOrEmpty(this.mFilePath)) | |
{ | |
if (obj is string) | |
{ | |
return ((string)obj).Equals(this.mFilePath); | |
} | |
else if (obj is PathInfo) | |
{ | |
PathInfo other = (PathInfo)obj; | |
return this.mFilePath.Equals(other.mFilePath); | |
} | |
} | |
return base.Equals(obj); | |
} | |
public override int GetHashCode() | |
{ | |
if (!string.IsNullOrEmpty(this.mFilePath)) | |
return this.mFilePath.GetHashCode(); | |
return base.GetHashCode(); | |
} | |
public override string ToString() | |
{ | |
if (!string.IsNullOrEmpty(this.mFilePath)) | |
return this.mFilePath; | |
return base.ToString(); | |
} | |
private static long CombineHighLowInts(uint high, uint low) | |
{ | |
return (((long)high) << 0x20) | low; | |
} | |
private static DateTime ConvertDateTime(uint high, uint low) | |
{ | |
long fileTime = CombineHighLowInts(high, low); | |
return DateTime.FromFileTimeUtc(fileTime).ToLocalTime(); | |
} | |
#endregion | |
#region Properties | |
/// <summary> | |
/// Contains display name of FileName. | |
/// </summary> | |
public string DisplayName | |
{ | |
get | |
{ | |
if (!string.IsNullOrEmpty(this.mFilePath)) | |
{ | |
SHFILEINFO psfi = new SHFILEINFO(); | |
if (SHGetFileInfo(this.mFilePath, 0, ref psfi, (uint)Marshal.SizeOf(psfi), (uint)SHGFI_DISPLAYNAME) > 0) | |
{ | |
return psfi.szDisplayName; | |
} | |
} | |
return ""; | |
} | |
} | |
public string FileName | |
{ | |
get { return this.mFileName; } | |
} | |
public string AlternateFileName | |
{ | |
get { return this.mAlternateFileName; } | |
} | |
/// <summary> | |
/// Defines file name or path, for which an icon extracts. | |
/// </summary> | |
public string FilePath | |
{ | |
get | |
{ | |
return this.mFilePath; | |
} | |
} | |
/// <summary> | |
/// Contains an icon associated with FileName. | |
/// </summary> | |
public System.Drawing.Icon Icon | |
{ | |
get | |
{ | |
if (!string.IsNullOrEmpty(this.mFilePath)) | |
{ | |
SHFILEINFO psfi = new SHFILEINFO(); | |
uint uFlags = (uint)SHGFI_ICON; | |
uFlags = this.mLargeIcon ? uFlags : uFlags; | |
uFlags = this.mLinkOverlay ? (uFlags | (uint)SHGFI_LINKOVERLAY) : uFlags; | |
uFlags = this.mSelected ? (uFlags | (uint)SHGFI_SELECTED) : uFlags; | |
if (SHGetFileInfo(this.mFilePath, 0, ref psfi, (uint)Marshal.SizeOf(psfi), uFlags) > 0) | |
{ | |
return System.Drawing.Icon.FromHandle(new IntPtr(psfi.hIcon)); | |
} | |
} | |
return null; | |
} | |
} | |
/// <summary> | |
/// Get the icon with link overlay. | |
/// </summary> | |
public System.Drawing.Icon LinkOverlayIcon | |
{ | |
get | |
{ | |
if (!string.IsNullOrEmpty(this.mFilePath)) | |
{ | |
SHFILEINFO psfi = new SHFILEINFO(); | |
uint uFlags = (uint)SHGFI_ICON | (uint)SHGFI_LINKOVERLAY; | |
if (SHGetFileInfo(this.mFilePath, 0, ref psfi, (uint)Marshal.SizeOf(psfi), uFlags) > 0) | |
{ | |
return System.Drawing.Icon.FromHandle(new IntPtr(psfi.hIcon)); | |
} | |
} | |
return null; | |
} | |
} | |
/// <summary> | |
/// Get the selected icon. | |
/// </summary> | |
public System.Drawing.Icon SelectedIcon | |
{ | |
get | |
{ | |
if (!string.IsNullOrEmpty(this.mFilePath)) | |
{ | |
SHFILEINFO psfi = new SHFILEINFO(); | |
uint uFlags = (uint)SHGFI_ICON | (uint)SHGFI_SELECTED; | |
if (SHGetFileInfo(this.mFilePath, 0, ref psfi, (uint)Marshal.SizeOf(psfi), uFlags) > 0) | |
{ | |
return System.Drawing.Icon.FromHandle(new IntPtr(psfi.hIcon)); | |
} | |
} | |
return null; | |
} | |
} | |
/// <summary> | |
/// Contains system icon index of FileName. | |
/// </summary> | |
public int SystemIconIndex | |
{ | |
get | |
{ | |
if (!string.IsNullOrEmpty(this.mFilePath)) | |
{ | |
SHFILEINFO psfi = new SHFILEINFO(); | |
if (SHGetFileInfo(this.mFilePath, 0, ref psfi, (uint)Marshal.SizeOf(psfi), (uint)SHGFI_SYSICONINDEX) > 0) | |
{ | |
return psfi.iIcon; | |
} | |
} | |
return -1; | |
} | |
} | |
/// <summary> | |
/// Contains type name of FileName. | |
/// </summary> | |
public string TypeName | |
{ | |
get | |
{ | |
if (!string.IsNullOrEmpty(this.mFilePath)) | |
{ | |
SHFILEINFO psfi = new SHFILEINFO(); | |
if (SHGetFileInfo(this.mFilePath, 0, ref psfi, (uint)Marshal.SizeOf(psfi), (uint)SHGFI_TYPENAME) > 0) | |
{ | |
return psfi.szTypeName; | |
} | |
} | |
return ""; | |
} | |
} | |
public FileAttributes Attributes | |
{ | |
get { return this.mAttributes; } | |
} | |
public DateTime CreationTime | |
{ | |
get { return this.mCreationTime; } | |
} | |
public DateTime LastAccesTime | |
{ | |
get { return this.mLastAccesTime; } | |
} | |
public DateTime LastWriteTime | |
{ | |
get { return this.mLastWriteTime; } | |
} | |
public long Length | |
{ | |
get { return this.mLength; } | |
} | |
#endregion | |
#region SHFILEINFO Class | |
/// <summary> | |
/// Structure that maps to SHFILEINFO | |
/// </summary> | |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] | |
internal sealed class SHFILEINFO | |
{ | |
public const int MAX_PATH = 260; | |
public int hIcon; | |
public int iIcon; | |
public uint dwAttributes; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] | |
public string szDisplayName; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] | |
public string szTypeName; | |
} | |
#endregion | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment