web-dev-qa-db-de.com

Der beste Weg, um den Dateipfad zu lange Ausnahme aufzulösen

Ich habe eine App erstellt, die alle Dokumentbibliotheken auf einer SP= Site herunterlädt, aber irgendwann gab sie mir diesen Fehler (ich habe versucht, auf Google zu suchen, konnte aber nichts finden, wenn jemand etwas weiß) Trick, um dieses Problem zu lösen, bitte antworten Sie andernfalls, danke, dass Sie es sich angeschaut haben.

System.IO.PathTooLongException: Der angegebene Pfad, der Dateiname oder beide sind zu lang. Der vollständig qualifizierte Dateiname darf nicht länger als 260 Zeichen sein und der Verzeichnisname darf nicht länger als 248 Zeichen sein. bei System.IO.Path.NormalizePathFast (String path, Boolean fullCheck) bei System.IO.Path.GetFullPathInternal (String path) bei 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
89
Muhammad Raja

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

Siehe hierzu MS-Artikel über das Benennen von Dateien, Pfaden und Namespaces

Hier ist ein Zitat aus dem Link:

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

Und ein paar Workarounds (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 path-length + name-length < MAX_PATH. Du könntest:

  • Einen Unterordner freigeben
  • Verwenden Sie die Befehlszeile, um mit SUBST einen Laufwerksbuchstaben zuzuweisen
  • Verwenden Sie AddConnection unter VB, um einem Pfad einen Laufwerksbuchstaben zuzuweisen
51
James Hill

Es gibt eine Bibliothek mit dem Namen Zeta Long Paths , die eine .NET-API zum Arbeiten mit langen Pfaden bietet.

Hier ist ein guter Artikel, der dieses Problem sowohl für .NET als auch für PowerShell behandelt: " . NET, PowerShell-Pfad zu lange Ausnahme und ein .NET PowerShell-Robocopy-Klon "

23
Tim Lewis

Die Lösung, die für mich funktioniert hat, war das Bearbeiten des Registrierungsschlüssels, um das Verhalten bei langen Pfaden zu ermöglichen, wobei der Wert auf 1 gesetzt wurde. 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

12
goonerify

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 (einschließlich Erweiterung).

2
Marcel Piquet

Sie können eine symbolische Verknüpfung mit einem kürzeren Verzeichnis erstellen. Zuerst Kommandozeile öffnen zum Beispiel durch Shift + RightClick in Ihrem gewünschten Ordner mit einem kürzeren Pfad (möglicherweise müssen Sie ihn als Administrator ausführen).

Dann tippe mit relativen oder absoluten Pfaden:

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

Und dann starten Sie die Lösung vom kürzeren Weg. Der Vorteil dabei ist: Sie müssen nichts bewegen.

2
Markus Weber

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

1
Lachezar Lalov

Ich kann die unten stehende Antwort aus meiner Erfahrung nicht für öffentlich zugängliche Webanwendungen empfehlen.

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 ihn von ungefähr 290 Zeichen auf 30 Zeichen reduzieren. :)

1
user1570636

Wenn Sie aufgrund eines langen Pfads ein Problem mit Ihren bin - Dateien haben, können Sie in Visual Studio 2015 zur Eigenschaftsseite des betreffenden Projekts wechseln und das relative Ausgabeverzeichnis ändern = zu einem kürzeren.

Z.B. bin\debug \ wird C:\_ bins\MyProject \

1
N-ate

Noch nicht erwähnt und ein Update, es gibt 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 Standardklassen von System.IO. Das auffälligste Manko des Standard-.NET-Systems.IO ist die mangelnde Unterstützung von erweiterten NTFS-Funktionen, insbesondere die Unterstützung von Pfaden mit erweiterter Länge (z. B. Datei-/Verzeichnispfade, die länger als 260 Zeichen sind).

0
Markus Hooge

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

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

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

0