134 votes

Meilleure façon de résoudre l'exception du chemin d'accès trop long

J'ai créé une application qui télécharge toutes les bibliothèques de documents d'un site SP, mais à un moment donné, elle me donne cette erreur (j'ai essayé de regarder sur google mais je n'ai rien trouvé, maintenant si quelqu'un connait une astuce pour résoudre ce problème, merci de me répondre sinon merci de regarder).

System.IO.PathTooLongException : Le chemin d'accès spécifié, le nom du fichier ou les deux sont trop longs. Le nom de fichier entièrement qualifié doit être inférieur à 260 caractères et le nom de répertoire doit être inférieur à 248 caractères. at System.IO.Path.NormalizePathFast(String path, Boolean fullCheck) at System.IO.Path.GetFullPathInternal(String path) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options) at System.IO.File.Create(String path)

il atteint la limite de la chaîne, le code est donné ci-dessous,

#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

71voto

James Hill Points 27532

La cause de l'erreur étant évidente, voici quelques informations qui devraient vous aider à résoudre le problème :

Voir ceci Article de MS sur l'attribution de noms aux fichiers, chemins et espaces de noms

Voici une citation tirée du lien :

Limitation de la longueur maximale du chemin Dans l'API Windows (à quelques exceptions près) d'un chemin d'accès est MAX_PATH, qui est définie comme étant de 260 caractères. Un chemin est structuré dans l'ordre suivant : lettre du lecteur, deux-points, barre oblique inverse, composants du nom séparés par des barres obliques inverses, et un caractère caractère nul. Par exemple, le chemin d'accès maximal sur le lecteur D est " D:\some chaîne de chemin de 256 caractères<NUL>" où "<NUL>" représente la chaîne de chemin invisible. invisible de la page de code du système actuel. (Les caractères sont utilisés ici pour des raisons de clarté visuelle et ne peuvent pas faire partie d'une chaîne de caractères. chaîne de chemin d'accès valide).

Et quelques solutions de contournement (tirées des commentaires) :

Il existe des moyens de résoudre les différents problèmes. L'idée de base des solutions énumérées ci-dessous est toujours la même : réduire la longueur du chemin afin d'avoir path-length + name-length < MAX_PATH . Vous pouvez :

  • Partager un sous-dossier
  • Utilisez la ligne de commande pour attribuer une lettre de lecteur au moyen de SUBST
  • Utiliser AddConnection sous VB pour attribuer une lettre de lecteur à un chemin d'accès

57voto

IQ_HiGh Points 83

La solution qui a fonctionné pour moi a consisté à modifier la clé de registre pour activer le comportement des chemins longs, en définissant la valeur 1. Il s'agit d'une nouvelle fonctionnalité opt-in pour Windows 10.

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

J'ai trouvé cette solution dans une section nommée de l'article qui @ james-hill affichée.

Nommer les fichiers, les chemins et les espaces de noms : Limitation de la longueur maximale des chemins d'accès

Dans les éditions de Windows antérieures à la version 1607 de Windows 10, la longueur maximale d'un chemin d'accès est MAX_PATH, définie à 260 caractères. Dans les versions ultérieures de Windows, la modification d'une clé de registre ou l'utilisation de l'outil Stratégie de groupe est nécessaire pour supprimer la limite. Voir Limitation de la longueur maximale des chemins d'accès pour plus de détails.


Voir aussi Limitation de la longueur maximale du chemin mentionné par @ dontbyteme .

Pour activer le nouveau comportement du long chemin, les deux conditions suivantes doivent être remplies :

  • La clé de registre Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled (Type: REG_DWORD) doit exister et avoir la valeur 1. La valeur de la clé sera mise en cache par le système (par processus) après le premier appel à une fonction Win32 de fichier ou de répertoire affectée (voir ci-dessous la liste des fonctions). La clé de registre ne sera pas rechargée pendant la durée de vie du processus. Pour que toutes les applications du système reconnaissent la valeur de la clé, un redémarrage peut être nécessaire car certains processus peuvent avoir démarré avant que la clé ne soit définie.
  • En manifeste de la demande doit également inclure le longPathAware élément.

    <application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings"> <ws2:longPathAware>true</ws2:longPathAware> </windowsSettings> </application>

25voto

Tim Lewis Points 1012

Il existe une bibliothèque appelée Zeta Longs Chemins qui fournit une API .NET pour travailler avec des chemins longs.

Voici un bon article qui couvre cette question pour .NET et PowerShell : " .NET, PowerShell Path too Long Exception et un clone de Robocopie PowerShell .NET "

9voto

Markus Weber Points 346

Vous pouvez créer un lien symbolique avec un répertoire plus court. Premiers liens symboliques ouvrir la ligne de commande par exemple par Shift + RightClick dans le dossier de votre choix avec un chemin d'accès plus court (il se peut que vous deviez l'exécuter en tant qu'administrateur).

Tapez ensuite des chemins relatifs ou absolus :

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

Puis reprendre la Solution par le chemin le plus court. L'avantage est le suivant : Il n'est pas nécessaire de déplacer quoi que ce soit.

5voto

Lachezar Lalov Points 379

Ce qui a fonctionné pour moi, c'est de déplacer mon projet tel qu'il était sur le bureau ( C:\Users\lachezar.l\Desktop\MyFolder ) à ( C:\0\MyFolder ) qui, comme vous pouvez le constater, utilise un chemin plus court et sa réduction a permis de résoudre le problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X