Dosya yolunu çözmenin en iyi yolu çok uzun istisna


109

Bir SP Sitesindeki tüm belge kitaplıklarını indiren bir uygulama oluşturdum, ancak bir noktada bana bu hatayı veriyor (google'a bakmayı denedim ama hiçbir şey bulamadım, şimdi biri bu sorunu çözmek için herhangi bir hile biliyorsa lütfen yanıt verin aksi halde teşekkürler bakmak için)

System.IO.PathTooLongException: Belirtilen yol, dosya adı veya her ikisi çok uzun. Tam nitelikli dosya adı 260 karakterden az olmalı ve dizin adı 248 karakterden az olmalıdır. System.IO.Path.NormalizePathFast at System.IO.Path.GetFullPathInternal (String path) at System.IO.FileStream.Init (Dize yolu, FileMode modu, FileAccess erişimi, Int32 hakları, Boolean useRights System.IO.FileStream..ctor'da FileShare paylaşımı, Int32 bufferSize, FileOptions seçenekleri, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy) (Dize yolu, FileMode modu, FileAccess erişimi, FileShare paylaşımı, Int32 bufferSize, FileOptions seçenekleri). IO.File.Create (Dize yolu)

string limitine ulaşır, Kod aşağıda verilmiştir,

#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
UNC (veya her neyse) yolunu 8.3 formatına dönüştürün. [CMD kullanarak 8.3 biçimine dönüştürün] [1] [1]: stackoverflow.com/questions/10227144/…
AutomationNation


Yanıtlar:


58

Hatanın nedeni açık olduğundan, sorunu çözmenize yardımcı olacak bazı bilgiler aşağıda verilmiştir:

Dosyaları, Yolları ve Ad Alanlarını Adlandırma hakkındaki bu MS makalesine bakın

İşte bağlantıdan bir alıntı:

Maksimum Yol Uzunluğu Sınırlaması Windows API'de (aşağıdaki paragraflarda açıklanan bazı istisnalar dışında), bir yol için maksimum uzunluk, 260 karakter olarak tanımlanan MAX_PATH'dir. Yerel bir yol aşağıdaki sırada yapılandırılır: sürücü harfi, iki nokta üst üste, ters eğik çizgi, ters eğik çizgilerle ayrılmış ad bileşenleri ve sonlandırıcı bir boş karakter. Örneğin, D sürücüsündeki maksimum yol "D: \ bazı 256 karakterlik yol dizesi <NUL>" olup burada "<NUL>", geçerli sistem kod sayfası için görünmez sonlandırma boş karakterini temsil eder. (<> Karakterleri burada görsel netlik için kullanılır ve geçerli bir yol dizesinin parçası olamaz.)

Ve birkaç geçici çözüm (yorumlardan alınmıştır):

Çeşitli sorunları çözmenin yolları vardır. Aşağıda listelenen çözümlerin temel fikri her zaman aynıdır: Sahip olmak için yol uzunluğunu azaltın path-length + name-length < MAX_PATH. Yapabilirsin:

  • Bir alt klasör paylaşın
  • SUBST aracılığıyla bir sürücü harfi atamak için komut satırını kullanın
  • Bir yola sürücü harfi atamak için VB altında AddConnection'ı kullanın

7
@TimeToThine, yayınladığım makaleyi okudun mu? Yorumları okudunuz mu? Yanılıyor olabilirim, ancak SO topluluğundan daha önce sağladığımdan daha fazla yardım alacağınızı sanmıyorum.
James Hill

2
Evet, sorumu buraya göndermeden önce okudum, hatta "\\? \" Denedim ama bir nedenden dolayı bu bağlamda çalışmıyor. Bu blogu kullanırken buluyorum, ancak bazı nedenlerden dolayı düzgün çalışmıyor, " codinghorror.com/blog/2006/08/shortening-long-file-paths.html " Hala dizini kayıtlı tutan bir şey arıyorum ve yapabiliyorum oradan alın veya bunun gibi bir şey, örneğin geçerli dizini string yerine kaydetmek için gizli bir etiket kullanın, ancak çalışıp çalışmayacağından emin olun.
Muhammed Raja

24
Açık ama mantıklı değil. Neden yol boyutu sınırlaması var ??? 2017.
Jaider

2
Directory.SetCurrentDirectory () kullanarak geçerli dizini klasörün dizinine değiştirirsem, bu kısıtlamayı önler. Yoksa sorun hala var mıdır?
Adam Lindsay

3
Makale güncellenmiş gibi görünüyor: Starting in Windows 10, version 1607, MAX_PATH limitations have been removed from common Win32 file and directory functions. Ancak bunu etkinleştirmek için kaydolmalı ve bir kayıt defteri anahtarı belirlemelisiniz.
Tom Deblauwe

28

Benim için işe yarayan çözüm, uzun yol davranışını etkinleştirmek için kayıt defteri anahtarını düzenlemek ve değeri 1 olarak ayarlamaktı. Bu, Windows 10 için yeni bir tercihli özelliktir.

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

Bu çözümü @ james-hill'in gönderdiği makalenin adlandırılmış bir bölümünden aldım.

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


2
Bunu 1 olarak ayarladım ve hala hatayı alıyorum, neden bu noktada bilmiyorum.
Mr Angry

Makale iki şarttan bahsediyor. Öncelikle kayıt defteri anahtarı ve ikinci olarak uygulama 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>Visual Studio 2019'da benim için, Visual Studio yeniden başlatıldıktan sonra bu ikinci gereksinim gerekli değildi.
Tom Anderson

Üzgünüm muhtemelen bu aptalca bir soru ama "xml uygulaması" nedir? Web.config mi yoksa başka bir şey mi? Web Sayfasında bu sorunu yaşıyorum asp.net projesi
Ondra Starenko

Yukarıda belirtildiği gibi, uygulama xml'sini değiştirmeden Visual Studio 2019'da (yeniden başlattıktan sonra) sorunsuz çalışır. Çözüm için teşekkürler.
Zoman

@TomAnderson: VS2017 kullanıyorum. Bu application.xml dosyasını nerede bulabilirim? 1. adımı yaptıktan sonra problemimi çözmez.
Sharad


3

Daha kısa bir dizinle sembolik bir bağlantı oluşturabilirsiniz. Önce komut satırını açın , örneğin Shift + RightClickistediğiniz klasörde daha kısa bir yolla (yönetici olarak çalıştırmanız gerekebilir).

Ardından göreceli veya mutlak yollarla yazın:

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

Ardından Çözümü daha kısa yoldan başlatın. Buradaki avantaj şudur: Hiçbir şeyi hareket ettirmek zorunda değilsiniz.


Bu, VS2015'te çalışmaz. VS'nin yolun uzunluğunu geçersiz kıldığı görülmektedir. VS2015 çözümü için N-Ate cevabına bakın.
N-ate

1
Yapabileceğiniz şey, çözüm klasörünü "subst" komutunu kullanarak bir sürücüye eşlemektir. Bu VS2017 için çalışıyor.
Filipe Calasans

2

Windows 8.1'de. NET 3.5, benzer bir sorun yaşadım.
Dosyamın adı yalnızca 239 karakter uzunluğunda olmasına rağmen, bir FileInfo nesnesini yalnızca dosya adıyla (yol olmadan) başlatmaya gittiğimde System türünde bir istisna oluştu. 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

Dosya adını 204 karaktere düşürerek sorunu çözdüm (uzantı dahil).


Bunu okuyan herkes için ek bilgi - Dosya adları 247 karakterle sınırlıdır ve tam yol 259 ile sınırlıdır. Dolayısıyla, dosya adınız 239 ise, yolun geri kalanı için yalnızca 20 karakter kalır (ör. "C: \ temp") . Dosya adını kırparsanız, TAM yolun 259 karakter veya daha az olduğundan emin olmanız gerekir.
Losbear

1

Uzun bir yol nedeniyle bin dosyalarınızla ilgili bir sorun yaşıyorsanız , Visual Studio 2015'te sorun teşkil eden projenin özellik sayfasına gidebilir ve ilgili Çıktı Dizini'ni daha kısa bir dizine değiştirebilirsiniz .

Örneğin bin \ debug \ olur C: \ _ kutular \ Projem \


1
Özellikleri yeniden açtıktan sonra, derlemem başarısız olduğunda yeni "c: \ vs \ bin \ Release" yolunun ".. \ .. \ .. \ .. \ .. \ .. \ .. \ olarak değiştirildiğini fark ettim . . \ vs \ bin \ Release \ " . ".. \" karakter sayımına dahil edilip edilmediğinden emin değilim .
samis

2
Çok uzun olarak değerlendirilen yollar mutlak yollardır.
N-yedi

1

Benim için işe yarayan şey, projemi masaüstünde olduğu gibi (C: \ Users \ lachezar.l \ Desktop \ MyFolder) (C: \ 0 \ MyFolder) 'a taşımaktı, bu da görebileceğiniz gibi daha kısa yol kullanıyor ve onu azalttı. sorun.


1

Deneyimlerime göre, herkese açık Web uygulamaları için aşağıdaki cevabımı önermeyeceğim.

Şirket içi aletleriniz veya Test için ihtiyacınız varsa, kendi makinenizde paylaşmanızı tavsiye ederim.

-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

Bu, daha sonra \\ {PCName} \ {YourSharedRootDirectory} gibi paylaşılan bir dizin oluşturacaktır. Bu, tam yolunuzdan kesinlikle çok daha az olabilir, benim için yaklaşık 290 karakterden 30 karaktere indirebilirim. :)


0

Şimdiye kadar ve bir güncellemeden bahsetmiyorum, çok uzun olan yolları işlemek için çok iyi kurulmuş bir kitaplık var. AlphaFS , .NET platformuna standart System.IO sınıflarından daha eksiksiz Win32 dosya sistemi işlevselliği sağlayan bir .NET kitaplığıdır. Standart .NET System.IO'nun en önemli eksikliği, gelişmiş NTFS özelliklerinin desteklenmemesidir, en önemlisi genişletilmiş uzunluk yolu desteği (örn. 260 karakterden uzun dosya / dizin yolları).


0

Bulabildiğim en iyi cevap, buradaki yorumlardan birinde. Birisinin yorumu kaçırmaması ve kesinlikle bunu denemesi için cevaba eklemek. Benim için sorunu çözdü.

Komut isteminde "alt" komutunu kullanarak çözüm klasörünü bir sürücüye eşlemeliyiz - örneğin, alt z:

Ve sonra çözümü bu sürücüden açın (bu durumda z). Bu, yolu olabildiğince kısaltabilir ve uzun dosya adı sorununu çözebilir.


0

Bu aynı zamanda muhtemelen bir çözüm olabilir. Bazen Geliştirme projenizi çok derin tuttuğunuzda da ortaya çıkar, proje dizininin çok fazla dizine sahip olabileceği anlamına gelir, bu yüzden lütfen çok fazla dizinin onu içindeki basit bir klasörde tutmasını sağlamayın. sürücüler. Örneğin - Ben de projem böyle tutulduğunda bu hatayı alıyordum-

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

sonra projemi içine yapıştırdım

D: \ Sharad \ LatestWorkings \ GenericSurveyApplication

Ve Sorun çözüldü.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.