MAX_PATH umgehen (Pfad länger als 260 Zeichen)

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von Eierlein.

    MAX_PATH umgehen (Pfad länger als 260 Zeichen)

    Hallo, mein erster Beitrag :) Normalerweise finde ich hier alles, aber zu diesem Thema habe ich nix gefunden.

    Mit Net Framework 4.6.2 sollte max_path eigentlich vermieden werden können. Toll dachte ich, endlich keine Limite betreffend Pfadlänge. Wenn ich also folgender Befehl schreibe in Visual Studio (VB) 2012 und Net Framework 4.6.2 anwende

    My.Computer.FileSystem.CopyFile(x,y)

    und dabei x wie auch y = sehr langer Pfad > 260 Zeichen habe, sollte das eigentlich funktionieren. Nein! Geht nicht, max_path Ausnahme wird zwar vermieden, aber es heisst dann "ein Teil des Pfades konnte nicht gefunden werden". Ich informiere mich und finde folgendes:

    "the \\?\ prefix not only enables long paths; it causes the path to be passed to the file system with minimal modification by the Windows APIs. A consequence is that \\?\ turns off file name normalization performed by Windows APIs"

    Also versuche ich folgendes:

    My.Computer.FileSystem.CopyFile("\\?\" & x,"\\?\" & y)

    Geht aber auch nicht. Dann kommt er mit "Erkennt Zeichen blabla nicht"

    Was mache ich falsch? Ich möchte nur Pfadangaben kopieren, die länger als 260 Zeichen sind... ?(

    Manu234211 schrieb:

    nix gefunden
    Willkommen im Forum. :thumbup:
    Ich schon. Gugst Du hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Der Präfix funktioniert nur, wenn die Unicode-Version der Windows API verwendet wird, der System.IO-Namespace verwendet aber die ANSI-Version.

    Die einzige Option, die du also hast, ist, alle Funktionen aus der Windows-API, die du brauchst, in ihrer Unicode-Version zu importieren.
    In oben verlinktem Thread ist ein Beispielcode dafür verlinkt.
    @Manu234211 Da musst Du zwischen den Zeilen lesen und die API bemühen: API.CreateFile.
    Das beste wäre, eine Klasse zu generieren, in der dann die API-Rufe gekapselt werden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Vielen Dank für eure Antworten. Da muss ich leider passen. Ich habe nochmals eine Stunde investiert und nach dem Thema gesucht. Leider fanden sich alle gefundenen Forenbeiträge bei meinem Problem wieder, also der Tatsache dass My.Computer.FileSystem.CopyFile("\\?\" & x,"\\?\" & y) eben nicht geht, weil das über Unicode gemacht werden muss. Dann jedoch wusste niemand eine Antwort.

    Der erwähnte Link von @Artentus vermutlich folgender:
    galratner.com/blogs/net/archiv…h-windows-native-api.aspx

    Ich habe es mir angeschaut, das ist für C# und nicht Net, ich habe es jedenfalls nicht re-produzieren können.

    Ich weiss auch nicht, ob das Ganze überhaupt nötig ist, wenn man sich folgenden Beitrag anschaut:
    blogs.msdn.microsoft.com/jerem…long-paths-on-windows-10/

    Ich habe ja gerade Net Framework 4.6.2 deshalb installiert.

    Vielleicht kann mir noch jemand weiterhelfen, ansonst muss ich halt in den sauren Apfel beissen und irgendwie künstlich die Pfade kürzen :whistling:
    C# ist .Net und lässt sich ohne Probleme 1 zu 1 in VB.Net übersetzen.(Naja bis auf ein paar winzige Ausnahmen, welche hier aber nicht drinnen sind und auch sehr selten zu finden sind), es gibt sogar Translator, die die meiste Arbeit für dich übernehmen.

    Also das Argument, das ist aber C# oder das ist aber VB.Net gilt in der .Net Welt nicht.

    Ansonsten scheint ja dein Link etwas zu sein, probiers doch einfach mal aus.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Hallo @Manu234211

    Der Code von Gal Ratner funktioniert bestens, und auf www.pinvoke.net gibt es sogar noch Beispiele.
    Noch besser kann man es doch gar nicht mehr kriegen.

    VB.NET-Quellcode

    1. Public Shared Function Copy(ByVal fromFileName As String, ByVal toFileName As String, ByVal overrideExisting As Boolean) As Boolean
    2. Dim formattedfromFileName As String = "\\?\" & fromFileName
    3. Dim formattedtoFileName As String = "\\?\" & toFileName
    4. If Not CopyFile(formattedfromFileName, formattedtoFileName, overrideExisting) Then
    5. Throw New Win32Exception()
    6. End If
    7. Return True
    8. End Function
    9. Public Shared Function CreateDirectory(ByVal dirPath As String) As Boolean
    10. Dim formatedPathName As String = "\\?\" & dirPath
    11. If Not CreateDirectory(formatedPathName, IntPtr.Zero) Then
    12. Throw New Win32Exception()
    13. End If
    14. Return True
    15. End Function
    16. Public Shared Function DeleteDirectory(ByVal lpPathName As String) As Boolean
    17. Dim formatedPathName As String = "\\?\" & lpPathName
    18. If Not RemoveDirectory(formatedPathName) Then
    19. Throw New Win32Exception()
    20. End If
    21. Return True
    22. End Function


    VB.NET-Quellcode

    1. <DllImport("kernel32.dll", CharSet:=CharSet.Unicode, SetLastError:=True)> _
    2. Private Shared Function CopyFile(ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal bFailIfExists As Boolean) As <MarshalAs(UnmanagedType.Bool)> Boolean
    3. End Function
    4. <DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> _
    5. Private Shared Function CreateDirectory(ByVal lpPathName As String, ByVal lpSecurityAttributes As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    6. End Function
    7. <DllImport("kernel32.dll", CharSet:=CharSet.Unicode, SetLastError:=True)> _
    8. Private Shared Function RemoveDirectory(ByVal lpPathName As String) As Boolean
    9. End Function


    Aufrufe

    VB.NET-Quellcode

    1. FileIONative.Delete(filePath)
    2. FileIONative.DeleteDirectory(path)
    3. FileIONative.CreateDirectory(path)
    4. FileIONative.Copy(path & fileName, filePath, True)


    Hier noch ein Code Converter

    Funktioniert.

    Freundliche Grüsse

    exc-jdbi
    Könnt ihr alle nicht lesen? Der Threadersteller hat selbst erwähnt, dass long path support mit .Net Framework 4.6.2 hinzugefügt wurde. Wie auch hier zu sehen ist. Dazu gehört auch das ​\\?\ prefix.

    @Manu234211:
    Dein Programm muss .Net Framework 4.6.2 als target framework haben oder du fügst das in deine App.config ein, dann kannst du auch .Net Framework 4, 4.5.x als target haben aber es muss .Net Framework 4.6.2 installiert sein:

    XML-Quellcode

    1. <runtime>
    2. <AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false;Switch.System.IO.BlockLongPaths=false"/>
    3. </runtime>


    Hab das mit folgenden Code getestet:

    VB.NET-Quellcode

    1. Dim path1 As String = "\\?\" & Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
    2. For i As Integer = 0 To 4
    3. Dim nodeName = String.Join("", Enumerable.Repeat(i, 100))
    4. path1 = Path.Combine(path1, nodeName)
    5. Next
    6. If Not Directory.Exists(path1) Then
    7. Directory.CreateDirectory(path1)
    8. End If
    9. Dim path2 As String = "\\?\" & Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
    10. For i As Integer = 5 To 9
    11. Dim nodeName = String.Join("", Enumerable.Repeat(i, 100))
    12. path2 = Path.Combine(path2, nodeName)
    13. Next
    14. If Not Directory.Exists(path2) Then
    15. Directory.CreateDirectory(path2)
    16. End If
    17. Dim f1 As String = Path.Combine(path1, "1.txt")
    18. Dim f2 As String = Path.Combine(path2, "2.txt")
    19. If Not File.Exists(f1) Then
    20. File.WriteAllText(f1, "hello")
    21. End If
    22. File.Copy(f1, f2)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Pinki“ ()

    vlt. kannst auch du einfach nicht lesen.
    Der obere Teil meines Posts war auf alles < 4.6.2 bezogen und im unteren Teil hab ich ihm gesagt, dass er das aus seinem eigenen Link doch einfach mal probieren soll(natürlich wenn er auf 4.6.2 angewiesen sein will)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Seid lieb zueinander ;)

    @Pinki: Ja! Geht!! Danke vielmals!!! Ich hatte mir nämlich extra VB 2012 installiert, da man hier die Framework Version selbst auswählen kann (hatte VB 2010). Dann hatte ich mir Framework 4.6.2 installiert und damit versucht, lange Pfade zu kopieren. Das hat nicht funktioniert, hatte es mit \\?\ auch versucht, und stellt euch vor, ich hatte im Code eine Replace Funktion eingebaut, um aus "\\" "\" zu machen um fehlerhafte Pfade zu korrigieren, weil der Pfad im Code zusammengesetzt wird. Das hatte dann Einfluss auf das Prefix und dann kam die Meldung, er erkennt das Symbol "?" nicht, weil VB den ganzen Prefix nicht richtig lesen konnte, da er aus \\?\ wohl \?\ machte. Mit dem Code von Pinki hatte ich nochmals einen Anlauf genommen und so herausgefunden, dass es tatsächlich geht. Ich habe mich nur gewundert, wie im Code von Pinki geschrieben wurde "File.Copy" ich hatte da immer "Io.File.Copy" machen müssen.

    Auch danke all den anderen für die Beiträge. Echt toll, wie schnell ihr geantwortet habt. Dieser Thread wird bestimmt noch oft gegoogelt werden, das Ganze ist ja ziemlich neu :)

    Manu234211 schrieb:

    Framework 4.6.2
    wird vom Studio 2012 noch nicht supportet, da müsstest Du zum Studio 2015 wechseln.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo,

    besser wäre es, solche lange Pfade zu vermeiden. Bei uns auf der Arbeit schreiben auch einige Kollegen halbe Romane in Ordner- und Dateinamen. Excel und Co öffnen das dann aber nicht mehr. Der Explorer passt auch nicht auf, wenn man kurze Ordnernamen in lange ändert. Die Dateien im letzten Ordner sind dann blockiert. Der Dir-Befehl auf der Kommandozeile (also mitgeliefertes von MS) meckert dann auch über zu lange Pfade.
    Gruß
    Peterfido

    Keine Unterstützung per PN!
    Unabhängig vom Framework reicht der API Aufruf.

    VB.NET-Quellcode

    1. Module Module1
    2. <DllImport("kernel32.dll", CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)> _
    3. Private Shared Function CopyFile(<MarshalAs(UnmanagedType.LPWStr)> ByVal lpExistingFileName As String, _
    4. <MarshalAs(UnmanagedType.LPWStr)> ByVal lpNewFileName As String, _
    5. <MarshalAs(UnmanagedType.Bool)> ByVal bFailIfExists As Boolean) As _
    6. <MarshalAs(UnmanagedType.Bool)> Boolean
    7. End Function
    8. Sub Main()
    9. Dim r As Boolean 'Rückgabewert False -> Fehler, True -> OK
    10. Dim z As String 'Zieldatei
    11. Dim q As String 'Quelldatei
    12. q = "\\?\" & Quelldatei
    13. z = Zieldatei
    14. r = CopyFile(q, z, 0) ' Falls Zieldatei vorhanden 1 -> nicht überschreiben, 0 -> überschreiben
    15. Console.WriteLine("Länge Quellpfad: " & q.Length.ToString)
    16. Console.WriteLine()
    17. Console.WriteLine("r = " & r.ToString)
    18. Console.Read()
    19. End Sub