4

NTFSでは、パスの前に\\?\文字シーケンスを付けて、260文字の制限を超えるパスであることを示すことができます。そのため、ファイルシステムはパスを正しく解釈し、を上げることを回避しPathTooLongExceptionます。

(詳細については、 http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx#maxpathを参照してください)

パス文字列の前にこのシーケンスを付ける.NETAPIはありますか、それとも自分で記述し続けていますか?

本質的に、私は以下に相当する方法を探しています。

static string ToExtendedPath(string path)
{
    if(Path.IsPathRooted(path))
    {
        return @"\\?\" + path;
    }

    return Path.Combine(@"\\?\", path);
}
4

2 に答える 2

6

いいえ、特定の「通常の」パスを拡張構文に変換する.NETAPIはありません。あなたはあなた自身を転がさなければなりません(ちなみに、それは些細なことです)。

注:CodyGrayとHansPassantが述べたように、.NET Frameworkは長い(拡張された)パスをサポートしていません。それらを操作する場合は、APIを直接使用する必要があります。また、すべてのAPI関数が長いパスをサポートしているわけではありません。一般的に、低レベルの関数はそうします。MSDNのドキュメントを参照してください。

私が行ったことは、関連するAPI関数(CreateFileなど)のラッパー関数を記述し、.NETファイルシステム関数の代わりにそれらのラッパーを呼び出すことです。

于 2011-07-29T08:13:02.107 に答える
0

@ helge-kleinが、260文字の制限を回避する.Net APIがないことを指摘したように、その機能は完全にOSに依存し、その一部は260max_path制限のレジストリベースのオーバーライドをサポートします。

[編集]DotNet4.6.2以降のサポート:System.IO.LongPathブログ、およびサンプル

Windows 10 Creators Updateは、カーネル(およびコマンドプロンプト)をMoveFileEx Wに拡張しましたが、dotnetReferenceSourceで明らかなように、拡張カーネルの使用はDotNetFrameworkSystem.IO.Fileに含まれていません。

#if FEATURE_CORESYSTEM
    [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
    [ResourceExposure(ResourceScope.Machine)]
    private static extern bool MoveFileEx(String src, String dst, uint flags);

    internal static bool MoveFile(String src, String dst)
    {
        return MoveFileEx(src, dst, 2 /* MOVEFILE_COPY_ALLOWED */);
    }
#else // FEATURE_CORESYSTEM
    [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
    [ResourceExposure(ResourceScope.Machine)]
    internal static extern bool MoveFile(String src, String dst);
#endif // FEATURE_CORESYSTEM

MoveFileをラップするLinqPadプログラムの例(他はpinvokeにあります)

void Main()
{
    //Create 3 files: in c:\temp\test\
    //testsrc0.txt, testsrc1.txt and testsrc2.txt
    //"\\?\UNC\server\share", 
    string src0File = @"\\?\UNC\127.0.0.1\c$\temp\test\testsrc0.txt";
    string dst0File = @"\\?\UNC\127.0.0.1\c$\temp\test\testdst0.txt";
    string dst0FileDotNet = @"c:\temp\test\testdst0.txt";
    string src1File = @"\\?\c:\temp\test\testsrc1.txt";
    string dst1File = @"\\?\c:\temp\test\testdst1.txt";
    string dst1FileDotNet = @"c:\temp\test\testdst1.txt";
    string src2File = @"\\?\\127.0.0.1\c$\temp\test\testsrc2.txt";
    string dst2File = @"\\?\\127.0.0.1\c$\temp\test\testdst2.txt";
    string dst2FileDotNet = @"c:\temp\test\testdst2.txt";

    MoveFileEx(src0File, dst0File, MoveFileFlags.MOVEFILE_REPLACE_EXISTING);
    System.IO.File.Exists(dst0File).Dump("File0 Exists");//FALSE
    System.IO.File.Exists(dst0FileDotNet).Dump("File0 Exists");//TRUE    

    MoveFileEx(src1File, dst1File, MoveFileFlags.MOVEFILE_REPLACE_EXISTING);
    System.IO.File.Exists(dst1File).Dump("File1 Exists");//FALSE
    System.IO.File.Exists(dst1FileDotNet).Dump("File1 Exists");//TRUE    

    MoveFileEx(src2File, dst2File, MoveFileFlags.MOVEFILE_REPLACE_EXISTING);
    System.IO.File.Exists(dst2File).Dump("File2 Exists");//FALSE
    System.IO.File.Exists(dst2FileDotNet).Dump("File2 Exists");//FALSE - as missing UNC keyword
    System.Runtime.InteropServices.Marshal.GetLastWin32Error().Dump("ERROR:");//3 == ERROR_PATH_NOT_FOUND
}

[Flags]
enum MoveFileFlags
{
    MOVEFILE_REPLACE_EXISTING = 0x00000001,
    MOVEFILE_COPY_ALLOWED = 0x00000002,
    MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004,
    MOVEFILE_WRITE_THROUGH = 0x00000008,
    MOVEFILE_CREATE_HARDLINK = 0x00000010,
    MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x00000020
}

// Define other methods and classes here
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, MoveFileFlags dwFlags);

ドライブとUNCパスを持つパスには、キーワード「UNC」が必要です。\?\ UNC \

于 2018-04-04T03:08:44.133 に答える