solution for PathTooLongException

M

Michael Heitland

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(Utils.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(lastWin32Error);
}
// 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top