Il modo migliore per risolvere l'eccezione troppo lunga del percorso del file


109

Ho creato un'app che scarica tutte le librerie di documenti in un sito SP, ma a un certo punto mi ha dato questo errore (ho provato a guardare google ma non sono riuscito a trovare nulla, ora se qualcuno conosce qualche trucco per risolvere questo problema per favore rispondi altrimenti grazie per guardarlo)

System.IO.PathTooLongException: il percorso, il nome file o entrambi specificati sono troppo lunghi. Il nome file completo deve contenere meno di 260 caratteri e il nome della directory deve contenere meno di 248 caratteri. in System.IO.Path.NormalizePathFast (percorso stringa, Boolean fullCheck) in System.IO.Path.GetFullPathInternal (percorso stringa) in System.IO.FileStream.Init (percorso stringa, modalità FileMode, accesso FileAccess, diritti Int32, useRights booleano , Condivisione FileShare, Int32 bufferSize, Opzioni FileOptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy) in System.IO.FileStream..ctor (percorso stringa, modalità FileMode, accesso FileAccess, condivisione FileShare, Int32 bufferSize, opzioni FileOptions) in System. IO.File.Create (percorso stringa)

raggiunge il limite per stringa, il codice è dato di seguito,

#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

1
Converti il ​​percorso UNC (o qualsiasi altra cosa) in un formato 8.3. [Converti in formato 8.3 utilizzando CMD] [1] [1]: stackoverflow.com/questions/10227144/…
AutomationNation


Possibile duplicato. Qui ho scoperto la soluzione stackoverflow.com/a/44211420/5312148
Francesco

Risposte:


58

Poiché la causa dell'errore è ovvia, ecco alcune informazioni che dovrebbero aiutarti a risolvere il problema:

Consulta questo articolo di MS sulla denominazione di file, percorsi e spazi dei nomi

Ecco una citazione dal link:

Limitazione della lunghezza massima del percorso Nell'API di Windows (con alcune eccezioni discusse nei paragrafi seguenti), la lunghezza massima per un percorso è MAX_PATH, che è definita come 260 caratteri. Un percorso locale è strutturato nel seguente ordine: lettera di unità, due punti, barra rovesciata, componenti del nome separati da barre rovesciate e un carattere null di terminazione. Ad esempio, il percorso massimo sull'unità D è "D: \ una stringa di percorso di 256 caratteri <NUL>" dove "<NUL>" rappresenta il carattere null invisibile di terminazione per la tabella codici di sistema corrente. (I caratteri <> sono usati qui per chiarezza visiva e non possono far parte di una stringa di percorso valida.)

E alcune soluzioni alternative (prese dai commenti):

Esistono modi per risolvere i vari problemi. L'idea di base delle soluzioni elencate di seguito è sempre la stessa: ridurre la lunghezza del percorso per avere path-length + name-length < MAX_PATH. Potresti:

  • Condividi una sottocartella
  • Utilizzare la riga di comando per assegnare una lettera di unità tramite SUBST
  • Utilizzare AddConnection in VB per assegnare una lettera di unità a un percorso

7
@TimeToThine, hai letto l'articolo che ho postato? Hai letto i commenti? Potrei sbagliarmi, ma non credo che riceverai altro aiuto dalla comunità SO, oltre a quello che ho già fornito.
James Hill

2
Sì, l'ho già letto prima di postare la mia domanda qui, ho anche provato "\\? \" Ma per qualche motivo non funziona in questo contesto. Trovo questo blog, lo sto usando ma per qualche motivo non funziona correttamente, " codinghorror.com/blog/2006/08/shortening-long-file-paths.html " Sto ancora cercando qualcosa che mantenga la directory salvata e posso prendilo da lì, o qualcosa del genere, ad esempio usa un'etichetta nascosta per salvare la directory corrente invece della stringa, ma non sono sicuro se funzionerà.
Muhammad Raja

24
È ovvio ma non ha alcun senso. Perché c'è una limitazione della dimensione del percorso ??? è il 2017.
Jaider

2
Se cambiassi la directory corrente nella directory della cartella utilizzando Directory.SetCurrentDirectory () eviterebbe questa restrizione. O il problema esisterebbe ancora.
Adam Lindsay

3
L'articolo sembra essere stato aggiornato: Starting in Windows 10, version 1607, MAX_PATH limitations have been removed from common Win32 file and directory functions. ma è necessario accettare e impostare una chiave di registro per abilitarlo.
Tom Deblauwe

28

La soluzione che ha funzionato per me è stata modificare la chiave di registro per abilitare il comportamento del percorso lungo, impostando il valore su 1. Questa è una nuova funzionalità di attivazione per Windows 10

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

Ho ottenuto questa soluzione da una sezione con nome dell'articolo che @ james-hill ha pubblicato.

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


2
Ho impostato questo valore su 1 e ricevo ancora l'errore, non ho idea del perché a questo punto.
Mr Angry

L'articolo menziona due requisiti. In primo luogo la chiave del Registro di sistema e in secondo luogo l'applicazione 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>per me in Visual Studio 2019, questo secondo requisito non era necessario dopo il riavvio di Visual Studio.
Tom Anderson

Mi dispiace, probabilmente questa è una domanda stupida, ma cos'è "application xml"? È web.config o qualcos'altro? Ho questo problema sulla pagina Web del progetto asp.net
Ondra Starenko

Come detto sopra, funziona bene in Visual Studio 2019 (dopo il riavvio) senza modificare l'xml dell'applicazione. Grazie per la soluzione.
Zoman

@ TomAnderson: Sto usando VS2017. Dove posso trovare questo application.xml? poiché dopo aver fatto il primo passaggio non risolve il mio problema.
Sharad,


3

È possibile creare un collegamento simbolico con una directory più breve. Per prima cosa apri la riga di comando, ad esempio, Shift + RightClicknella cartella desiderata con un percorso più breve (potresti doverlo eseguire come amministratore).

Quindi digita con percorsi relativi o assoluti:

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

Quindi avvia la soluzione dal percorso più breve. Il vantaggio qui è: non devi spostare nulla.


Questo non funziona in VS2015. Sembrerebbe che VS preveda la lunghezza del percorso. Vedi la risposta N-Ate per il work-around VS2015.
N-ate

1
Quello che puoi fare è mappare la cartella della soluzione a un driver utilizzando il comando "subst". Funziona per VS2017.
Filipe Calasans

2

In Windows 8.1, utilizzando. NET 3.5, ho avuto un problema simile.
Sebbene il nome del mio file fosse lungo solo 239 caratteri quando sono andato a istanziare un oggetto FileInfo con solo il nome del file (senza percorso) si è verificata un'eccezione di tipo System. 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

Ho risolto il problema tagliando il nome del file a 204 caratteri (estensione inclusa).


Informazioni aggiuntive per chiunque legga questo: i nomi dei file sono limitati a 247 caratteri mentre il percorso completo è limitato a 259. Quindi, se il nome del file è 239, rimangono solo 20 caratteri per il resto del percorso (ad esempio "c: \ temp") . Se tagli il nome del file, devi assicurarti che il percorso COMPLETO sia di 259 caratteri o meno.
Losbear

1

Se hai un problema con i tuoi file bin a causa di un lungo percorso, in Visual Studio 2015 puoi andare alla pagina delle proprietà del progetto incriminato e cambiare la relativa directory di output in una più breve.

Ad esempio bin \ debug \ diventa C: \ _ bins \ MyProject \


1
Dopo aver riaperto le proprietà quando la mia compilazione non è riuscita, ho notato che il nuovo percorso "c: \ vs \ bin \ Release" è stato sostituito come ".. \ .. \ .. \ .. \ .. \ .. \ .. \. . \ vs \ bin \ Release \ " . Non sono sicuro che ".. \" venga preso in considerazione nel conteggio dei caratteri.
samis

2
I percorsi valutati come troppo lunghi sono percorsi assoluti.
N-ate

1

Quello che ha funzionato per me è stato spostare il mio progetto com'era sul desktop (C: \ Users \ lachezar.l \ Desktop \ MyFolder) in (C: \ 0 \ MyFolder) che, come puoi vedere, utilizza un percorso più breve e riducendolo ha risolto il problema problema.


1

Dalla mia esperienza, non consiglierò la mia risposta di seguito per applicazioni Web rivolte al pubblico.

Se ne hai bisogno per i tuoi strumenti interni o per i test, ti consiglio di condividerlo sulla tua macchina.

-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

Questo creerà quindi una directory condivisa come \\ {PCName} \ {YourSharedRootDirectory} Questo potrebbe essere decisamente molto inferiore al tuo percorso completo, spero, per me potrei ridurre a 30 caratteri da circa 290 caratteri. :)


0

Non si parla di finora e di un aggiornamento, c'è una libreria molto ben consolidata per la gestione dei percorsi troppo lunghi. AlphaFS è una libreria .NET che fornisce funzionalità di file system Win32 più complete alla piattaforma .NET rispetto alle classi System.IO standard. La carenza più notevole dello standard .NET System.IO è la mancanza di supporto delle funzionalità avanzate di NTFS, in particolare il supporto di percorsi di lunghezza estesa (ad esempio percorsi di file / directory più lunghi di 260 caratteri).


0

La migliore risposta che riesco a trovare è in uno dei commenti qui. Aggiungendolo alla risposta in modo che qualcuno non perda il commento e dovrebbe assolutamente provarlo. Ha risolto il problema per me.

Dobbiamo mappare la cartella della soluzione su un'unità utilizzando il comando "subst" nel prompt dei comandi, ad esempio subst z:

Quindi apri la soluzione da questa unità (z in questo caso). Ciò ridurrebbe il percorso il più possibile e potrebbe risolvere il lungo problema del nome del file.


0

questa potrebbe essere anche una possibile soluzione Alcune volte si verifica anche quando mantieni il tuo progetto di sviluppo troppo in profondità, significa che potrebbe essere possibile che la directory del progetto abbia troppe directory quindi per favore non creare troppe directory tenerlo in una semplice cartella all'interno del unità. Ad esempio, ho ricevuto questo errore anche quando il mio progetto è stato mantenuto in questo modo-

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

poi ho semplicemente incollato il mio progetto all'interno

D: \ Sharad \ LatestWorkings \ GenericSurveyApplication

E il problema è stato risolto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.