PathTooLongException C# 4.5

2019-01-25 21:54发布

问题:

I having trouble of copying some folder 260+ chars (for example: 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) to some other place with standart DrectoryInfo.Create(); adding \?\ or \?\UNC\ (like "\\?\UNC\") just throw another ArgumentException. What am i doing wrong? What else i can do without using Directory.SetCurrentDirectory() ?

回答1:

Yes, using the standard APIs will give you this kind of limitations (255 chars IIRC).

From .NET you can use the AlphaFS project which lets you use very long paths (using the "\\?\" style) and mimics the System.IO namespace.

You will probably be able to use this library just as if you were using System.IO, for example : AlphaFS.Win32.Filesystem.File.Copy() instead System.IO.File.Copy()

If you don't want or cannot use AlphaFS you'll have to pinvoke the Win32 API



回答2:

Actually you need to call win32 from c#. We have done this

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);
    }
}

A sample code:

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");
}


回答3:

There's a great library on Microsoft TechNet for overcoming the long filenames problem, it's called Delimon.Win32.I​O Library (V4.0) and it has its own versions of key methods from System.IO

For example, you would replace:

System.IO.Directory.GetFiles

with

Delimon.Win32.IO.Directory.GetFiles

which will let you handle long files and folders.

From the website:

Delimon.Win32.IO replaces basic file functions of System.IO and supports File & Folder names up to up to 32,767 Characters.

This Library is written on .NET Framework 4.0 and can be used either on x86 & x64 systems. The File & Folder limitations of the standard System.IO namespace can work with files that have 260 characters in a filename and 240 characters in a folder name (MAX_PATH is usually configured as 260 characters). Typically you run into the System.IO.PathTooLongException Error with the Standard .NET Library.