To traverse folders recursively that contain files with a path 260 chars we can use Unicode versions of FindFirst and FindNext and prefix all paths with NTFS escape sequence '\\?\'.
Files can be opened using SafeFileHandle and Win32 Api function CreateFile.
Here is the code:
/// <summary>
/// count files in starting folder and it's subfolders and retrieve the longest folder (not file!) path
/// </summary>
/// <param name="backgroundWorker">backgroundWorker</param>
/// <param name="e">arguments of backgroundWorker</param>
/// <param name="startFolderPathLong">full path of start folder (long form)</param>
/// <param name="startFolderShortForm">full path of start folder (truncated form)</param>
/// <returns>total number of files in folder (including subfolders)</returns>
int CountFilesInFolder(BackgroundWorker backgroundWorker, DoWorkEventArgs e, string startFolderPathLong, string startFolderShortForm)
{
try
{
if (backgroundWorker != null && backgroundWorker.CancellationPending)
{
e.Cancel = true;
return 0;
}
int numFiles = 0;
Win32Api._WIN32_FIND_DATAW fndData = new Win32Api._WIN32_FIND_DATAW();
IntPtr hFile = Win32Api.FindFirstFileW(_ntfsPrefix + startFolderPathLong + "*", ref fndData); // skip '.'
Win32Api.FindNextFileW(hFile, ref fndData); // skip '..'
int numFilesInThisFolder = 0;
while (Win32Api.FindNextFileW(hFile, ref fndData))
{
if (hFile.ToInt32() == -1)
{
throw new Exception(string.Format("FindNextFileW() in folder '{0}') failed: {1}",
startFolderPathLong,
Marshal.GetLastWin32Error()));
}
else
{
if ((fndData.dwFileAttributes & Win32Api.FILE_ATTRIBUTE_DIRECTORY) == Win32Api.FILE_ATTRIBUTE_DIRECTORY)
{
string folderPathLong = Utils.AppendPathSeparator(startFolderPathLong + fndData.cFileName);
string folderPathShort = Utils.AppendPathSeparator(Utils.RemoveNTFSPrefix(U tils.ToShortPathName(_ntfsPrefix + folderPathLong)));
numFiles += CountFilesInFolder(backgroundWorker, e, folderPathLong, folderPathShort);
if (e.Cancel || (backgroundWorker != null && backgroundWorker.CancellationPending))
{
return 0;
}
}
else // if ((fndData.dwFileAttributes & FILE_ATTRIBUTE_FILE) == FILE_ATTRIBUTE_FILE)
{
++numFilesInThisFolder;
}
}
}
Win32Api.FindClose(hFile);
if (numFilesInThisFolder 0)
{
if (startFolderShortForm.Length Settings.Default.MaxFolderPathShortLength)
{
string msg = string.Format("Length of folder ({0}) path exceeds MaxFolderPathShortLength ({1}) for folder '{2}' (long path = '{3}'",
startFolderShortForm.Length, Settings.Default.MaxFolderPathShortLength, startFolderShortForm, startFolderPathLong);
Error(msg);
}
if (startFolderShortForm.Length _longestFolderPathWithoutFileNameShortForm.Length)
{
_longestFolderPathWithoutFileNameShortForm = startFolderShortForm;
}
}
return numFiles + numFilesInThisFolder;
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.ToString() );
return 0;
}
}
public static byte[] ReadAllBytes(string filePathSrc)
{
try
{
SafeFileHandle fileHandle = Win32Api.CreateFile(
filePathSrc,
Win32Api.EFileAccess.GenericRead,
Win32Api.EFileShare.Read,
IntPtr.Zero,
Win32Api.ECreationDisposition.OpenExisting,
0,
IntPtr.Zero);
int lastWin32Error = Marshal.GetLastWin32Error();
if (fileHandle.IsInvalid)
{
throw new System.ComponentModel.Win32Exception(lastWin32Erro r);
}
// Pass the file handle to FileStream. FileStream will close the handle
using (FileStream fileStream = new FileStream(fileHandle, FileAccess.Read))
{
byte[] fileData = new byte[fileStream.Length];
if (fileStream.Length != fileStream.Read(fileData, 0, (int)fileStream.Length))
{
throw new Exception(string.Format("cannot read file '{0}'", filePathSrc));
}
return fileData;
}
}
catch (Exception ex)
{
throw new Exception(string.Format("cannot read from file '{0}': {1}",
filePathSrc, ex.ToString()));
}
}
EggHeadCafe.com - .NET Developer Portal of Choice
http://www.eggheadcafe.com