[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

System.IO.PathTooLongException - file name 260 character limitation

Posted on 2008-11-18
4
Medium Priority
?
6,126 Views
Last Modified: 2012-05-05
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

0
Comment
Question by:grummite
  • 2
  • 2
4 Comments
 
LVL 11

Expert Comment

by:William
ID: 22989185
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
 

Author Comment

by:grummite
ID: 22989257
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
 
LVL 11

Expert Comment

by:William
ID: 22989269
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
 

Accepted Solution

by:
grummite earned 0 total points
ID: 23049241
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

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Well, all of us have seen the multiple EXCEL.EXE's in task manager that won't die even if you call the .close, .dispose methods. Try this method to kill any excels in memory. You can copy the kill function to create a check function and replace the …
Microsoft Reports are based on a report definition, which is an XML file that describes data and layout for the report, with a different extension. You can create a client-side report definition language (*.rdlc) file with Visual Studio, and build g…
Integration Management Part 2
This lesson discusses how to use a Mainform + Subforms in Microsoft Access to find and enter data for payments on orders. The sample data comes from a custom shop that builds and sells movable storage structures that are delivered to your property. …
Suggested Courses

834 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question