web-dev-qa-db-ja.com

ファイルパスが長すぎる例外を解決する最良の方法

SPサイトのすべてのドキュメントライブラリをダウンロードするアプリを作成しましたが、ある時点でこのエラーが発生しました(グーグルを見てみましたが、解決するトリックを知っている人はいませんでした。この問題はそれ以外の場合は回答してください。

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共有、Int32 bufferSize、FileOptionsオプション、SECURITY_ATTRIBUTES secAttrs、String msgPath、Boolean bFromProxy)System.IO.FileStream..ctor(Stringパス、FileModeモード、FileAccessアクセス、FileShare共有、Int32 bufferSize、FileOptionsオプション)。 IO.File.Create(String path)

文字列の制限に達した場合、コードは以下のとおりです。

#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

エラーの原因は明らかであるため、問題の解決に役立つ情報を以下に示します。

これを参照してください ファイル、パス、名前空間の命名に関するMS記事

リンクからの引用です:

最大パス長の制限Windows APIでは(次の段落で説明するいくつかの例外を除く)、パスの最大長はMAX_PATHであり、次のように定義されます。 260文字。ローカルパスは、ドライブ文字、コロン、バックスラッシュ、バックスラッシュで区切られた名前コンポーネント、および終端のヌル文字の順序で構成されます。たとえば、ドライブDの最大パスは「D:\ some 256-character path string <NUL>」で、「<NUL>」は現在のシステムコードページの非表示の終了ヌル文字を表します。 (ここでは文字<>は見やすくするために使用されており、有効なパス文字列の一部にすることはできません。)

また、いくつかの回避策(コメントから引用):

さまざまな問題を解決する方法があります。以下にリストされているソリューションの基本的な考え方は常に同じです。path-length + name-length < MAX_PATHを使用するには、パスの長さを短くします。してもいいです:

  • サブフォルダーを共有する
  • コマンドラインを使用して、SUBSTを使用してドライブ文字を割り当てます
  • VBの下のAddConnectionを使用して、ドライブ文字をパスに割り当てます
51
James Hill

長いパスで動作する.NET APIを提供する Zeta Long Paths というライブラリがあります。

.NETとPowerShellの両方に関するこの問題をカバーする優れた記事を次に示します。「 。NET、PowerShellパスが長すぎる例外、および.NET PowerShell Robocopy Clone

23
Tim Lewis

私のために働いた解決策は、レジストリキーを編集して長いパスの動作を有効にし、値を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

12
goonerify

Windows 8.1では、使用。 NET 3.5、同様の問題がありました。
。 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文字(拡張子を含む)にトリミングする問題を解決しました。

2
Marcel Piquet

短いディレクトリでシンボリックリンクを作成できます。最初にコマンドラインを開くたとえば、目的のフォルダー内のShift + RightClickを使用して、パスを短くします(管理者として実行する必要がある場合があります)。

次に、相対パスまたは絶対パスで入力します。

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

そして、短いパスからソリューションを開始します。ここでの利点は、何も移動する必要がないことです。

2
Markus Weber

私のために働いたのは、デスクトップ(C:\ Users\lachezar.l\Desktop\MyFolder)にあったプロジェクトを(C:\ 0\MyFolder)に移動することです。問題。

1
Lachezar Lalov

私の経験から、公開されているWebアプリケーションについては、以下の回答はお勧めしません。

社内のツールやテストに必要な場合は、自分のマシンで共有することをお勧めします。

-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

これにより、\\ {PCName}\{YourSharedRootDirectory}のような共有ディレクトリが作成されます。これは、希望するフルパスよりも間違いなくずっと小さく、約290文字から30文字に減らすことができます。 :)

1
user1570636

パスが長いためにbinファイルに問題がある場合、Visual Studio 2015では、問題のプロジェクトのプロパティページに移動して、相対出力ディレクトリより短いものに。

例えば。 bin\debug \C:\ _ bins\MyProject\

1
N-ate

これまでのところ言及せず、更新もありますが、長すぎるパスを処理するための非常によく確立されたライブラリがあります。 AlphaFS は、標準のSystem.IOクラスよりも完全なWin32ファイルシステム機能を.NETプラットフォームに提供する.NETライブラリです。標準の.NET System.IOの最も顕著な欠点は、高度なNTFS機能のサポートの欠如、特に顕著な長さのパスサポート(たとえば、260文字を超えるファイル/ディレクトリパス)です。

0
Markus Hooge

私が見つけることができる最良の答えは、ここのコメントの1つです。回答に追加して、誰かがコメントを見逃さないようにし、間違いなくこれを試してください。それは私のために問題を修正しました。

コマンドプロンプトで「subst」コマンドを使用して、ソリューションフォルダーをドライブにマップする必要があります。例:subst z:

そして、このドライブ(この場合はz)からソリューションを開きます。これにより、パスができるだけ短くなり、ファイル名の問題が解決される可能性があります。

0