grummite
asked on
System.IO.PathTooLongException - file name 260 character limitation
Here is the exception description:
{"The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters."}
Using Visual Basic 2005, I received a System.IO.PathTooLongExcep tion exception when I am trying to copying a file from one long directory to another long. The files I am trying to copy are all 40 characters in length. Changing the directory structure is not an option. Using 8 character filenames with a ~1 is also not an option since this is a good change some of the files first 6 characters might be the same.
I looked at the http://blogs.msdn.com/bclteam/archive/2007/03/26/long-paths-in-net-part-2-of-3-long-path-workarounds-kim-hamilton.aspx MSDN website but this doesn't show how to do it in Visual Basic.
I am really stuck on this one. Any help would be greatly appreciated.
Code I used to test this is below. Both folders already exist and as I said before all files being copied are 40 characters in length.
{"The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters."}
Using Visual Basic 2005, I received a System.IO.PathTooLongExcep
I looked at the http://blogs.msdn.com/bclteam/archive/2007/03/26/long-paths-in-net-part-2-of-3-long-path-workarounds-kim-hamilton.aspx MSDN website but this doesn't show how to do it in Visual Basic.
I am really stuck on this one. Any help would be greatly appreciated.
Code I used to test this is below. Both folders already exist and as I said before all files being copied are 40 characters in length.
Imports System.IO
Public Class Form1
Public Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim folderpath, DestFolderPath As String
folderpath = "C:\Documents and Settings\USERABC\Local Settings\Application Data\ABCD\WORKSPACE\ABCDEFGHIJKLMNOPQRSTUVWXYZ\ABCDEFGH\ABCDEFGH\Applications\1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_AA_AAAAAAAAAAAAAAAAAAAAAAAAAA"
DestFolderPath = "C:\Documents and Settings\USERABC\Local Settings\Application Data\ABCDTEMP\WORKSPACE\ABCDEFGHIJKLMNOPQRSTUVWXYZ\ABCDEFGH\ABCDEFGH\Applications\1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_AA_AAAAAAAAAAAAAAAAAAAAAAAAAA"
Dim Sourcefolder, Destfolder As System.IO.DirectoryInfo
Sourcefolder = New System.IO.DirectoryInfo(folderpath)
Destfolder = New System.IO.DirectoryInfo(DestFolderPath)
For Each fi As FileInfo In Sourcefolder.GetFiles
My.Computer.FileSystem.CopyFile(fi.FullName, DestFolderPath & "\" & fi.Name)
Next
End Sub
End Class
ASKER
BillyDvd-
Thanks for you comment. The user will not have administrator access and will not be able to map a network drive to C$. Do you know of aonther way to map a directory? I know the old DOS SUBST command can do it but I rather not call a DOS command within the VB code.
Thanks for you comment. The user will not have administrator access and will not be able to map a network drive to C$. Do you know of aonther way to map a directory? I know the old DOS SUBST command can do it but I rather not call a DOS command within the VB code.
Here is the code from the article you refered to in vb...
' This code snippet is provided under the Microsoft Permissive License.
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
Imports Microsoft.Win32.SafeHandles
Imports System.Collections.Generic
Namespace FileHelper
<Flags> _
Public Enum EFileAccess As UInteger
GenericRead = &H80000000
GenericWrite = &H40000000
GenericExecute = &H20000000
GenericAll = &H10000000
End Enum
<Flags> _
Public Enum EFileShare As UInteger
None = &H0
Read = &H1
Write = &H2
Delete = &H4
End Enum
Public Enum ECreationDisposition As UInteger
[New] = 1
CreateAlways = 2
OpenExisting = 3
OpenAlways = 4
TruncateExisting = 5
End Enum
<Flags> _
Public Enum EFileAttributes As UInteger
[Readonly] = &H1
Hidden = &H2
System = &H4
Directory = &H10
Archive = &H20
Device = &H40
Normal = &H80
Temporary = &H100
SparseFile = &H200
ReparsePoint = &H400
Compressed = &H800
Offline = &H1000
NotContentIndexed = &H2000
Encrypted = &H4000
Write_Through = &H80000000
Overlapped = &H40000000
NoBuffering = &H20000000
RandomAccess = &H10000000
SequentialScan = &H8000000
DeleteOnClose = &H4000000
BackupSemantics = &H2000000
PosixSemantics = &H1000000
OpenReparsePoint = &H200000
OpenNoRecall = &H100000
FirstPipeInstance = &H80000
End Enum
<StructLayout(LayoutKind.Sequential)> _
Public Structure SECURITY_ATTRIBUTES
Public nLength As Integer
Public lpSecurityDescriptor As IntPtr
Public bInheritHandle As Integer
End Structure
Public Class FileIOHelp
<StructLayout(LayoutKind.Sequential)> _
Friend Structure FILETIME
Friend dwLowDateTime As UInteger
Friend dwHighDateTime As UInteger
End Structure
<StructLayout(LayoutKind.Sequential, CharSet := CharSet.Unicode)> _
Friend Structure WIN32_FIND_DATA
Friend dwFileAttributes As FileAttributes
Friend ftCreationTime As FILETIME
Friend ftLastAccessTime As FILETIME
Friend ftLastWriteTime As FILETIME
Friend nFileSizeHigh As Integer
Friend nFileSizeLow As Integer
Friend dwReserved0 As Integer
Friend dwReserved1 As Integer
<MarshalAs(UnmanagedType.ByValTStr, SizeConst := MAX_PATH)> _
Friend cFileName As String
' not using this
<MarshalAs(UnmanagedType.ByValTStr, SizeConst := 14)> _
Friend cAlternate As String
End Structure
Friend Shared INVALID_HANDLE_VALUE As New IntPtr(-1)
Friend Shared FILE_ATTRIBUTE_DIRECTORY As Integer = &H10
Friend Const MAX_PATH As Integer = 260
<DllImport("kernel32.dll", SetLastError := True, CharSet := CharSet.Unicode)> _
Friend Shared Function CreateFile(ByVal lpFileName As String, ByVal dwDesiredAccess As EFileAccess, ByVal dwShareMode As EFileShare, ByVal lpSecurityAttributes As IntPtr, ByVal dwCreationDisposition As ECreationDisposition, ByVal dwFlagsAndAttributes As EFileAttributes, _
ByVal hTemplateFile As IntPtr) As SafeFileHandle
End Function
Public Shared Sub TestCreateAndWrite(ByVal fileName As String)
Dim formattedName As String = "\\?\" & fileName
' Create a file with generic write access
Dim fileHandle As SafeFileHandle = CreateFile(formattedName, EFileAccess.GenericWrite, EFileShare.None, IntPtr.Zero, ECreationDisposition.CreateAlways, 0, _
IntPtr.Zero)
' Check for errors
Dim lastWin32Error As Integer = Marshal.GetLastWin32Error()
If fileHandle.IsInvalid Then
Throw New System.ComponentModel.Win32Exception(lastWin32Error)
End If
' Pass the file handle to FileStream. FileStream will close the
' handle
Using fs As New FileStream(fileHandle, FileAccess.Write)
fs.WriteByte(80)
fs.WriteByte(81)
fs.WriteByte(83)
fs.WriteByte(84)
End Using
End Sub
<DllImport("kernel32.dll", CharSet := CharSet.Unicode)> _
Friend Shared Function FindFirstFile(ByVal lpFileName As String, ByRef lpFindFileData As WIN32_FIND_DATA) As IntPtr
End Function
<DllImport("kernel32.dll", CharSet := CharSet.Unicode)> _
Friend Shared Function FindNextFile(ByVal hFindFile As IntPtr, ByRef lpFindFileData As WIN32_FIND_DATA) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError := True)> _
<Return: MarshalAs(UnmanagedType.Bool)> _
Friend Shared Function FindClose(ByVal hFindFile As IntPtr) As Boolean
End Function
' Assume dirName passed in is already prefixed with \\?\
Public Shared Function FindFilesAndDirs(ByVal dirName As String) As List(Of String)
Dim results As New List(Of String)()
Dim findData As WIN32_FIND_DATA
Dim findHandle As IntPtr = FindFirstFile(dirName & "\*", findData)
If findHandle <> INVALID_HANDLE_VALUE Then
Dim found As Boolean
Do
Dim currentFileName As String = findData.cFileName
' if this is a directory, find its contents
If (CInt(findData.dwFileAttributes) And FILE_ATTRIBUTE_DIRECTORY) <> 0 Then
If currentFileName & "." & (currentFileName & "..") Then
Dim childResults As List(Of String) = FindFilesAndDirs(Path.Combine(dirName, currentFileName))
' add children and self to results
results.AddRange(childResults)
results.Add(Path.Combine(dirName, currentFileName))
End If
Else
' it's a file; add it to the results
results.Add(Path.Combine(dirName, currentFileName))
End If
' find next
found = FindNextFile(findHandle, findData)
Loop While found
End If
' close the find handle
FindClose(findHandle)
Return results
End Function
End Class
End Namespace
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Use Long Path Tool, Long Path Tool can simplify and probably end your problems in unlocking, managing and renaming files that appear to have a long filename.
This would leave your path intact and you could just call the new drive letter ....
SO instead of
C:\Documents and Settings\USERABC\Local Settings\Application Data\ABCD\WORKSPACE\ABCDEF
You could have:
P:\Applications\1AAAAAAAAA