Beste Weg, um Dateipfad zu lange Ausnahme aufzulösen

108

Ich habe eine App erstellt, die alle Dokumentbibliotheken auf einer SP-Site herunterlädt, aber irgendwann wurde mir dieser Fehler angezeigt (ich habe versucht, auf Google zu schauen, konnte aber nichts finden. Wenn jemand einen Trick zur Lösung dieses Problems kennt, antworten Sie bitte anderweitig, danke für das Anschauen)

System.IO.PathTooLongException: Der angegebene Pfad, Dateiname oder beide sind zu lang. Der vollständig qualifizierte Dateiname muss weniger als 260 Zeichen und der Verzeichnisname weniger als 248 Zeichen enthalten. at System.IO.Path.NormalizePathFast (String path, Boolean fullCheck) at System.IO.Path.GetFullPathInternal (String path) at System.IO.FileStream.Init (String path, FileMode-Modus, FileAccess-Zugriff, Int32-Rechte, Boolean useRights , FileShare-Freigabe, Int32 bufferSize, FileOptions-Optionen, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy) bei System.IO.FileStream..ctor (String-Pfad, FileMode-Modus, FileAccess-Zugriff, FileShare-Freigabe, Int32 bufferSize, FileOptions-Optionen) bei System. IO.File.Create (String path)

es erreicht die Grenze für Zeichenfolge, Code ist unten angegeben,

#region Downloading Schemes

    private void btnDownload_Click(object sender, EventArgs e)
    {
        TreeNode currentNode = tvWebs.SelectedNode;
        SPObjectData objectData = (SPObjectData)currentNode.Tag;
        try
        {
            CreateLoggingFile();
            using (SPWeb TopLevelWeb = objectData.Web)
            {
                if(TopLevelWeb != null)
                    dwnEachWeb(TopLevelWeb, TopLevelWeb.Title, tbDirectory.Text);
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine(string.Format("Exception caught when tried to pass TopLevelWeb:{1}, Title = {2}, object data to (dwnEachWeb_method), Exception: {0}", ex.ToString(), objectData.Web, objectData.Title));
        }
        finally
        {
            CloseLoggingFile();
        }
    }

    private void dwnEachWeb(SPWeb TopLevelWeb, string FolderName, string CurrentDirectory)
    {
        if (TopLevelWeb != null)
        {
            if (TopLevelWeb.Webs != null)
            {
                CurrentDirectory = CurrentDirectory + "\\" + TopLevelWeb.Title;
                CreateFolder(CurrentDirectory);
                foreach (SPWeb ChildWeb in TopLevelWeb.Webs)
                {

                    dwnEachWeb(ChildWeb, ChildWeb.Title, CurrentDirectory);
                    ChildWeb.Dispose();
                }
                dwnEachList(TopLevelWeb, CurrentDirectory);
                //dwnEachList(TopLevelWeb, FolderName, CurrentDirectory);
            }
        }
    }

    private void dwnEachList(SPWeb oWeb, string CurrentDirectory)
    {
        foreach (SPList oList in oWeb.Lists)
        {
            if (oList is SPDocumentLibrary && !oList.Hidden)
            {
                dwnEachFile(oList.RootFolder, CurrentDirectory);
            }
        }
    }

    private void dwnEachFile(SPFolder oFolder, string CurrentDirectory)
    {
        if (oFolder.Files.Count != 0)
        {
            CurrentDirectory = CurrentDirectory + "\\" + oFolder.Name;
            CreateFolder(CurrentDirectory);
            foreach (SPFile ofile in oFolder.Files)
            {
                if (CreateDirectoryStructure(CurrentDirectory, ofile.Url))
                {
                    var filepath = System.IO.Path.Combine(CurrentDirectory, ofile.Url);
                    byte[] binFile = ofile.OpenBinary();
                    System.IO.FileStream fstream = System.IO.File.Create(filepath);
                    fstream.Write(binFile, 0, binFile.Length);
                    fstream.Close();
                }
            }
        }
    }

    //creating directory where files will be download        
    private bool CreateDirectoryStructure(string baseFolder, string filepath)
    {
        if (!Directory.Exists(baseFolder)) return false;

        var paths = filepath.Split('/');

        for (var i = 0; i < paths.Length - 1; i++)
        {
            baseFolder = System.IO.Path.Combine(baseFolder, paths[i]);
            Directory.CreateDirectory(baseFolder);
        }
        return true;
    }

    //creating folders
    private bool CreateFolder(string CurrentDirectory)
    {
        if (!Directory.Exists(CurrentDirectory))
        {
            Directory.CreateDirectory(CurrentDirectory);
        }
        return true;
    }

    //shorting string

    #endregion
Muhammad Raja
quelle
1
Konvertieren Sie den UNC-Pfad (oder was auch immer) in ein 8.3-Format. [Mit CMD in das 8.3-Format konvertieren] [1] [1]: stackoverflow.com/questions/10227144/…
AutomationNation
Mögliches Duplikat von Wie vermeide ich System.IO.PathTooLongException?
Deantwo
Mögliches Duplikat. Hier fand ich die Lösung stackoverflow.com/a/44211420/5312148
Francesco

Antworten:

57

Da die Ursache des Fehlers offensichtlich ist, finden Sie hier einige Informationen, die Ihnen bei der Lösung des Problems helfen sollen:

Weitere Informationen zum Benennen von Dateien, Pfaden und Namespaces finden Sie in diesem MS-Artikel

Hier ist ein Zitat aus dem Link:

Maximale Pfadlängenbeschränkung In der Windows-API (mit einigen Ausnahmen, die in den folgenden Absätzen erläutert werden) beträgt die maximale Länge für einen Pfad MAX_PATH, die als 260 Zeichen definiert ist. Ein lokaler Pfad ist in der folgenden Reihenfolge strukturiert: Laufwerksbuchstabe, Doppelpunkt, Backslash, durch Backslashes getrennte Namenskomponenten und ein abschließendes Nullzeichen. Beispielsweise ist der maximale Pfad auf Laufwerk D "D: \ eine 256-Zeichen-Pfadzeichenfolge <NUL>", wobei "<NUL>" das unsichtbare abschließende Nullzeichen für die aktuelle Systemcodepage darstellt. (Die Zeichen <> werden hier aus Gründen der visuellen Klarheit verwendet und können nicht Teil einer gültigen Pfadzeichenfolge sein.)

Und ein paar Problemumgehungen (aus den Kommentaren entnommen):

Es gibt Möglichkeiten, die verschiedenen Probleme zu lösen. Die Grundidee der unten aufgeführten Lösungen ist immer dieselbe: Reduzieren Sie die Pfadlänge, um zu haben path-length + name-length < MAX_PATH. Du darfst:

  • Teilen Sie einen Unterordner
  • Verwenden Sie die Befehlszeile, um mithilfe von SUBST einen Laufwerksbuchstaben zuzuweisen
  • Verwenden Sie AddConnection unter VB, um einem Pfad einen Laufwerksbuchstaben zuzuweisen
James Hill
quelle
7
@TimeToThine, hast du den Artikel gelesen, den ich gepostet habe? Hast du die Kommentare gelesen? Ich könnte mich irren, aber ich glaube nicht, dass Sie von der SO-Community mehr Hilfe bekommen werden, als ich bereits bereitgestellt habe.
James Hill
2
Ja, ich habe bereits gelesen, dass ich vor dem Posten meiner Frage hier sogar "\\? \" Versucht habe, aber aus irgendeinem Grund funktioniert es in diesem Zusammenhang nicht. Ich finde dieses Blog, benutze es, aber aus irgendeinem Grund funktioniert es nicht richtig. " Codinghorror.com/blog/2006/08/shortening-long-file-paths.html " Ich suche immer noch nach etwas, das das Verzeichnis gespeichert hält und ich kann Nehmen Sie es von dort oder so, zum Beispiel verwenden Sie eine versteckte Bezeichnung, um das aktuelle Verzeichnis anstelle einer Zeichenfolge zu speichern, aber nicht sicher, ob es funktionieren wird.
Muhammad Raja
24
Es ist offensichtlich, aber es macht keinen Sinn. Warum gibt es eine Pfadgrößenbeschränkung ??? es ist 2017.
Jaider
2
Wenn ich das aktuelle Verzeichnis mithilfe von Directory.SetCurrentDirectory () in das Verzeichnis des Ordners ändern würde, würde dies diese Einschränkung vermeiden. Oder würde das Problem noch bestehen.
Adam Lindsay
3
Der Artikel scheint aktualisiert worden zu sein: Starting in Windows 10, version 1607, MAX_PATH limitations have been removed from common Win32 file and directory functions. Sie müssen sich jedoch anmelden und einen Registrierungsschlüssel festlegen, um ihn zu aktivieren.
Tom Deblauwe
28

Die Lösung, die für mich funktioniert hat, bestand darin, den Registrierungsschlüssel zu bearbeiten, um das Verhalten bei langen Pfaden zu aktivieren, und den Wert auf 1 zu setzen. Dies ist eine neue Anmeldefunktion für Windows 10

HKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled (Type: REG_DWORD)

Ich habe diese Lösung aus einem benannten Abschnitt des Artikels erhalten, den @ james-hill gepostet hat.

https://docs.microsoft.com/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation

goonerify
quelle
2
Ich habe diesen Wert auf 1 gesetzt und erhalte immer noch den Fehler, keine Ahnung warum an dieser Stelle.
Mr Angry
Der Artikel erwähnt zwei Anforderungen. Erstens der Registrierungsschlüssel und zweitens die Anwendungs-XML: <application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings xmlns:ws2="https://schemas.microsoft.com/SMI/2016/WindowsSettings"> <ws2:longPathAware>true</ws2:longPathAware> </windowsSettings> </application>Für mich in Visual Studio 2019 war diese zweite Anforderung nach dem Neustart von Visual Studio nicht erforderlich.
Tom Anderson
Es tut mir leid, wahrscheinlich ist das eine dumme Frage, aber was ist "application xml"? Ist es web.config oder etwas anderes? Ich habe dieses Problem auf der Webseite asp.net Projekt
Ondra Starenko
Wie oben erwähnt, funktioniert es in Visual Studio 2019 (nach dem Neustart) einwandfrei, ohne die Anwendungs-XML zu ändern. Danke für die Lösung.
Zoman
@ TomAnderson: Ich benutze VS2017. Wo finde ich diese application.xml? wie nach dem 1. Schritt löst mein Problem nicht.
Sharad
3

Sie können einen symbolischen Link mit einem kürzeren Verzeichnis erstellen. Erste offene Befehlszeile beispielsweise durch Shift + RightClickin den gewünschten Ordner mit einem kürzeren Pfad (Sie es als Administrator ausgeführt werden kann).

Geben Sie dann mit relativen oder absoluten Pfaden ein:

mklink ShortPath\To\YourLinkedSolution C:\Path\To\Your\Solution /D

Starten Sie dann die Lösung auf dem kürzeren Weg. Der Vorteil hierbei ist: Sie müssen nichts bewegen.

Markus Weber
quelle
Dies funktioniert in VS2015 nicht. Es scheint, dass VS die Länge des Pfades dominiert. Siehe N-Ate-Antwort für die VS2015-Problemumgehung.
N-ate
1
Sie können den Lösungsordner mit dem Befehl "subst" einem Treiber zuordnen. Das funktioniert für VS2017.
Filipe Calasans
2

Unter Windows 8.1 mit. NET 3.5 hatte ich ein ähnliches Problem.
Obwohl der Name meiner Datei nur 239 Zeichen lang war, als ich ein FileInfo-Objekt mit nur dem Dateinamen (ohne Pfad) instanziierte, trat eine Ausnahme vom Typ System auf. IO.PathTooLongException

2014-01-22 11:10:35 DEBUG LogicalDOCOutlookAddIn.LogicalDOCAddIn - fileName.Length: 239 
2014-01-22 11:10:35 ERROR LogicalDOCOutlookAddIn.LogicalDOCAddIn - Exception in ImportEmail System.IO.PathTooLongException: Percorso e/o nome di file specificato troppo lungo. Il nome di file completo deve contenere meno di 260 caratteri, mentre il nome di directory deve contenere meno di 248 caratteri.
   in System.IO.Path.NormalizePathFast(String path, Boolean fullCheck)
   in System.IO.FileInfo..ctor(String fileName)
   in LogicalDOCOutlookAddIn.LogicalDOCAddIn.GetTempFilePath(String fileName) in C:\Users\alle\Documents\Visual Studio 2010\Projects\MyAddin1Outlook20072010\MyAddin1Outlook20072010\LogicalDOCAddIn.cs:riga 692
   in LogicalDOCOutlookAddIn.LogicalDOCAddIn.ImportEmail(_MailItem mailItem, OutlookConfigXML configXML, Int64 targetFolderID, String SID) in C:\Users\alle\Documents\Visual Studio 2010\Projects\MyAddin1Outlook20072010\MyAddin1Outlook20072010\LogicalDOCAddIn.cs:riga 857
   in LogicalDOCOutlookAddIn.LogicalDOCAddIn.ImportEmails(Explorers explorers, OutlookConfigXML configXML, Int64 targetFolderID, Boolean suppressResultMB) in C:\Users\alle\Documents\Visual Studio 2010\Projects\MyAddin1Outlook20072010\MyAddin1Outlook20072010\LogicalDOCAddIn.cs:riga 99

Ich habe das Problem behoben, bei dem der Dateiname auf 204 Zeichen gekürzt wurde (Erweiterung enthalten).

Marcel Piquet
quelle
Zusätzliche Informationen für alle, die dies lesen - Dateinamen sind auf 247 Zeichen begrenzt, während der vollständige Pfad auf 259 begrenzt ist. Wenn Ihr Dateiname also 239 ist, bleiben nur 20 Zeichen für den Rest des Pfads (z. B. "c: \ temp"). . Wenn Sie den Dateinamen kürzen, müssen Sie sicherstellen, dass der vollständige Pfad maximal 259 Zeichen enthält.
Losbear
1

Wenn Sie aufgrund eines langen Pfads ein Problem mit Ihren Bin- Dateien haben, können Sie in Visual Studio 2015 zur Eigenschaftenseite des betreffenden Projekts wechseln und das relative Ausgabeverzeichnis in ein kürzeres ändern .

Zum Beispiel ist \ debug \ wird C: \ _ bins \ MyProject \

N-aß
quelle
1
Nach dem erneuten Öffnen der Eigenschaften, als mein Build fehlschlug, bemerkte ich, dass der neue Pfad "c: \ vs \ bin \ Release" durch ".. \ .. \ .. \ .. \ .. \ .. \ .. \" ersetzt wurde. . \ vs \ bin \ Release \ " . Ich bin nicht sicher, ob ".. \" in die Anzahl der Zeichen einbezogen wird.
Samis
2
Als zu lang bewertete Pfade sind absolute Pfade.
N-aß
1

Was für mich funktioniert hat, ist das Verschieben meines Projekts auf dem Desktop (C: \ Users \ lachezar.l \ Desktop \ MyFolder) nach (C: \ 0 \ MyFolder) Problem.

Lachezar Lalov
quelle
1

Aus meiner Erfahrung heraus wird meine unten stehende Antwort nicht für öffentlich zugängliche Webanwendungen empfohlen.

Wenn Sie es für Ihre internen Tools oder zum Testen benötigen, würde ich empfehlen, es auf Ihrem eigenen Computer freizugeben.

-Right click on the root path you need to access
-Choose Properties
-Click on Share button and add your chosen users who can access it

Dadurch wird ein freigegebenes Verzeichnis wie \\ {PCName} \ {YourSharedRootDirectory} erstellt. Dies könnte definitiv viel weniger sein als Ihr vollständiger Pfad. Ich hoffe, ich könnte von ungefähr 290 Zeichen auf 30 Zeichen reduzieren. :) :)

Riyaz Hameed
quelle
0

Bisher nicht erwähnt und ein Update, gibt es eine sehr gut etablierte Bibliothek für den Umgang mit zu langen Pfaden. AlphaFS ist eine .NET-Bibliothek, die der .NET-Plattform umfassendere Win32-Dateisystemfunktionen bietet als die Standard-System.IO-Klassen. Der auffälligste Mangel des standardmäßigen .NET System.IO ist die mangelnde Unterstützung erweiterter NTFS-Funktionen, insbesondere der Unterstützung von Pfaden mit erweiterter Länge (z. B. Datei- / Verzeichnispfade mit mehr als 260 Zeichen).

Markus
quelle
0

Die beste Antwort, die ich finden kann, ist in einem der Kommentare hier. Fügen Sie es der Antwort hinzu, damit jemand den Kommentar nicht verpasst und dies auf jeden Fall ausprobieren sollte. Es hat das Problem für mich behoben.

Wir müssen den Lösungsordner mit dem Befehl "subst" in der Eingabeaufforderung einem Laufwerk zuordnen, z. B. subst z:

Öffnen Sie dann die Lösung von diesem Laufwerk (in diesem Fall z). Dies würde den Pfad so weit wie möglich verkürzen und könnte das langwierige Problem mit dem Dateinamen lösen.

Jatin Nath Prusty
quelle
0

Dies kann auch möglicherweise eine Lösung sein. Manchmal tritt es auch auf, wenn Sie Ihr Entwicklungsprojekt zu tief halten. Dies bedeutet, dass das Projektverzeichnis möglicherweise zu viele Verzeichnisse enthält. Stellen Sie daher bitte nicht zu viele Verzeichnisse auf, um es in einem einfachen Ordner innerhalb des zu speichern fährt. Zum Beispiel: Ich habe diesen Fehler auch erhalten, als mein Projekt so beibehalten wurde.

D: \ Sharad \ LatestWorkings \ GenericSurveyApplication020120 \ GenericSurveyApplication \ GenericSurveyApplication

dann habe ich einfach mein projekt eingefügt

D: \ Sharad \ LatestWorkings \ GenericSurveyApplication

Und das Problem wurde gelöst.

user3820036
quelle