[c#] 파일 경로가 너무 긴 예외를 해결하는 가장 좋은 방법

SP 사이트에서 모든 문서 라이브러리를 다운로드하는 앱을 만들었지 만 한 번에이 오류가 발생했습니다 (Google을 보려고했지만 아무것도 찾을 수 없었습니다. 이제이 문제를 해결하는 트릭을 아는 사람이 있으면 그렇지 않으면 응답 해주세요. 그것을보고)

System.IO.PathTooLongException : 지정된 경로, 파일 이름 또는 둘 다 너무 깁니다. 완전한 파일 이름은 260 자 미만이어야하며 디렉토리 이름은 248 자 미만이어야합니다. 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 (문자열 경로)

문자열 한도에 도달하면 코드는 아래와 같습니다.

#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



답변

오류의 원인은 분명하므로 문제 해결에 도움이되는 몇 가지 정보는 다음과 같습니다.

파일, 경로 및 네임 스페이스 이름 지정에 대한MS 문서를 참조하십시오.

다음은 링크의 인용문입니다.

최대 경로 길이 제한 Windows API (다음 단락에서 설명하는 일부 예외 포함)에서 경로의 최대 길이는 260 자로 정의되는 MAX_PATH입니다. 로컬 경로는 드라이브 문자, 콜론, 백 슬래시, 백 슬래시로 구분 된 이름 구성 요소 및 종료 널 문자의 순서로 구성됩니다. 예를 들어, D 드라이브의 최대 경로는 “D : \ some 256 자 경로 문자열 <NUL>”입니다. 여기서 “<NUL>”은 현재 시스템 코드 페이지에 대해 보이지 않는 종료 널 문자를 나타냅니다. (여기서 <> 문자는 시각적 명확성을 위해 사용되며 유효한 경로 문자열의 일부가 될 수 없습니다.)

그리고 몇 가지 해결 방법 (댓글에서 가져옴) :

다양한 문제를 해결하는 방법이 있습니다. 아래 나열된 솔루션의 기본 아이디어는 항상 동일 path-length + name-length < MAX_PATH합니다.. 당신은 할 수있다:

  • 하위 폴더 공유
  • 명령 줄을 사용하여 SUBST를 통해 드라이브 문자를 할당합니다.
  • VB에서 AddConnection을 사용하여 경로에 드라이브 문자를 할당합니다.

답변

나를 위해 일한 솔루션은 긴 경로 동작을 사용하도록 레지스트리 키를 편집하여 값을 1로 설정하는 것이 었습니다. 이것은 Windows 10의 새로운 옵트 인 기능입니다.

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

이 솔루션은 @ james-hill이 게시 한 기사의 명명 된 섹션에서 얻었습니다.

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


답변

긴 경로 에서 작동하는 .NET API를 제공하는 Zeta Long Paths 라는 라이브러리가 있습니다 .

다음은 .NET 및 PowerShell 모두에 대해이 문제를 다루는 좋은 기사입니다. ” .NET, PowerShell 경로가 너무 김 예외 및 .NET PowerShell Robocopy 클론


답변

더 짧은 디렉토리로 심볼릭 링크를 만들 수 있습니다. 예를 들어 경로가 더 짧은 원하는 폴더에서 먼저 명령 줄엽니 다Shift + RightClick (관리자 권한으로 실행해야 할 수 있음).

그런 다음 상대 또는 절대 경로로 입력합니다.

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

그런 다음 더 짧은 경로에서 솔루션을 시작하십시오. 여기에서 장점은 : 아무것도 이동할 필요가 없다는 것입니다.


답변

Windows 8.1에서. NET 3.5에서도 비슷한 문제가 발생했습니다.
파일 이름 (경로 없음)만으로 FileInfo 개체를 인스턴스화하려고했을 때 내 파일 이름이 239 자에 불과했지만 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

파일 이름을 204 자 (확장자 포함)로 자르는 문제를 해결했습니다.


답변

긴 경로로 인해 bin 파일에 문제가있는 경우 Visual Studio 2015에서 문제가되는 프로젝트의 속성 페이지로 이동하여 상대 출력 디렉터리 를 더 짧은 디렉터리 로 변경할 수 있습니다 .

예 : bin \ debug \C : \ _ bins \ MyProject \가됩니다.


답변

나를 위해 일한 것은 데스크탑 (C : \ Users \ lachezar.l \ Desktop \ MyFolder)에 있던 내 프로젝트를 (C : \ 0 \ MyFolder)로 옮기는 것입니다. 문제.