5

一部のフォルダを260文字以上コピーできません(例:F:\ NNNNNNNNNNNNNNNN \ NNNNNNNNNNN \ ROOT \ $ RECYCLE.BIN \ S-1-5-21-3299053755-4209892151-505108915-1000 \ $ RMSL3U8 \ NNNNNNNNN NNNNNNNN \ NNNNNNNNNNN \ NNNNNNNNNN \ NNNNNNNNNN \ publish \ Application Files \ TNNNNNNNNNNNN_1_0_0_0 \ NNNNNNNNNNNN.exe.manifest)標準のDrectoryInfo.Create();を使用して他の場所に移動します。\?\または\?\ UNC \( "\\?\ UNC \"など)を追加すると、別のArgumentExceptionがスローされます。私は何が間違っているのですか?Directory.SetCurrentDirectory()を使用せずに他に何ができますか?

4

3 に答える 3

8

実際には、c# から win32 を呼び出す必要があります。私たちはこれを行いました

using System;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

public static class LongPath
{
    static class Win32Native
    {
        [StructLayout(LayoutKind.Sequential)]
        public class SECURITY_ATTRIBUTES
        {
            public int nLength;
            public IntPtr pSecurityDescriptor;
            public int bInheritHandle;
        }

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CreateDirectory(string lpPathName, SECURITY_ATTRIBUTES lpSecurityAttributes);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, FileShare dwShareMode, SECURITY_ATTRIBUTES securityAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);
    }

    public static bool CreateDirectory(string path)
    {
        return Win32Native.CreateDirectory(String.Concat(@"\\?\", path), null);
    }

    public static FileStream Open(string path, FileMode mode, FileAccess access)
    {
        SafeFileHandle handle = Win32Native.CreateFile(String.Concat(@"\\?\", path), (int)0x10000000, FileShare.None, null, mode, (int)0x00000080, IntPtr.Zero);
        if (handle.IsInvalid)
        {
            throw new System.ComponentModel.Win32Exception();
        }
        return new FileStream(handle, access);
    }
}

サンプルコード:

string path = @"c:\".PadRight(255, 'a');
LongPath.CreateDirectory(path);

path = String.Concat(path, @"\", "".PadRight(255, 'a'));
LongPath.CreateDirectory(path);

string filename = Path.Combine(path, "test.txt");

FileStream fs = LongPath.Open(filename, FileMode.CreateNew, FileAccess.Write);

using (StreamWriter sw = new StreamWriter(fs))
{
    sw.WriteLine("abc");
}
于 2012-10-05T13:31:58.913 に答える
8

Microsoft TechNet には、長いファイル名の問題を克服するための優れたライブラリがあります。これはDelimon.Win32.I O Library (V4.0)と呼ばれ、System.IO の主要なメソッドの独自のバージョンがあります。

たとえば、次のように置き換えます。

System.IO.Directory.GetFiles

Delimon.Win32.IO.Directory.GetFiles

これにより、長いファイルとフォルダーを処理できます。

ウェブサイトから:

Delimon.Win32.IO は、System.IO の基本的なファイル機能を置き換え、最大 32,767 文字のファイルとフォルダ名をサポートします。

このライブラリは .NET Framework 4.0 で作成されており、x86 および x64 システムで使用できます。標準の System.IO 名前空間のファイルとフォルダーの制限は、ファイル名が 260 文字、フォルダー名が 240 文字のファイルで機能します (通常、MAX_PATH は 260 文字として構成されます)。通常、標準 .NET ライブラリで System.IO.PathTooLongException エラーが発生します。

于 2013-02-16T06:01:34.367 に答える
5

はい、標準 API を使用すると、この種の制限が適用されます (255 文字の IIRC)。

.NET から、非常に長いパス (「\\?\」スタイルを使用) を使用できるようにし、System.IO 名前空間を模倣するAlphaFS プロジェクトを使用できます。

System.IO を使用しているかのように、このライブラリを使用できる可能性があります。例: AlphaFS.Win32.Filesystem. System.IO の代わりにFile.Copy()File.Copy()

AlphaFS を使用したくない、または使用できない場合は、Win32 API をピンボークする必要があります。

于 2012-10-05T13:23:18.527 に答える