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.PathTooLongException 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.

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

Open in new window

grummiteAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

WilliamCommented:
Can you map the directory or a partial and work around it that way...
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\ABCDEFGHIJKLMNOPQRSTUVWXYZ\ABCDEFGH\ABCDEFGH\Applications\1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_AA_AAAAAAAAAAAAAAAAAAAAAAAAAA"


You could have:
P:\Applications\1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_AA_AAAAAAAAAAAAAAAAAAAAAAAAAA"
0
grummiteAuthor Commented:
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.
0
WilliamCommented:
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 

Open in new window

0
grummiteAuthor Commented:
I found a solution to this question at http://social.msdn.microsoft.com/forums/en-US/vblanguage/thread/cfa8a7f2-14e0-461f-90c1-a72f67d55774/.  This definitely was a tricky one.

Thanks anyway for your help.


0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Micahel LeblanCommented:
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.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.