А вообще странная ситуация:
Directory.CreateDirectory(myLongPath) работает только из пакета Pri.LongPath (да и его пришлось подписывать строгим именем);
File.WriteAllLines(myLongPath, lines) работает только из Delimon.dll.
Задействовать все прочее у меня не получилось...
Здравствуйте, mDmitriy, Вы писали:
D>А вообще странная ситуация: D>Directory.CreateDirectory(myLongPath) работает только из пакета Pri.LongPath (да и его пришлось подписывать строгим именем); D>File.WriteAllLines(myLongPath, lines) работает только из Delimon.dll. D>Задействовать все прочее у меня не получилось...
Сам совсем недавно решал такую проблему для работы с длинными путями.
Тут без WinApi не обойтись.
Могу подкинуть если нужно
Теоретически нет разницы между теорией и практикой, но на практике она есть
Здравствуйте, seimur, Вы писали: S>Сам совсем недавно решал такую проблему для работы с длинными путями. S>Тут без WinApi не обойтись. S>Могу подкинуть если нужно
Буду благодарен...
Re: Как создать файл по пути длиной более 256 символов?
Здравствуйте, mDmitriy, Вы писали:
D>Путь outputPath состоит из десятка подкаталогов, но общая длина более 256 символов D>Как быть?
В первую очередь я бы пересмотрел алгоритм — если он оперирует сущностями, которые уже превышают пределы, никто не гарантирует, что завтра вы не превысите даже расширенные пределы. Да и странновато как-то использовать данные для генерации путей хранения (а если там кракозябры-двоеточия-бэкслэши?). В похожей задаче, где надо было хранить кэш URL'ек, я вычислял хэш и уже из него делал файл.
Re: Как создать файл по пути длиной более 256 символов?
Здравствуйте, mDmitriy, Вы писали:
D>Здравствуйте, seimur, Вы писали: S>>Сам совсем недавно решал такую проблему для работы с длинными путями. S>>Тут без WinApi не обойтись. S>>Могу подкинуть если нужно D>Буду благодарен...
namespace System.IO.LongPathExtension
{
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
/// <summary>
/// Usefull extension methods to work with collections.
/// </summary>
public static class CollectionExtension
{
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items)
{
foreach (var item in items)
{
collection.Add(item);
}
}
public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
foreach (var item in collection)
{
action(item);
}
}
}
/// <summary>
///
/// </summary>
public class FileSystemObject
{
private const string SearchAllCriteria = "*";
/// <summary>
/// Returns path to file system object.
/// </summary>
public string Path { get; private set; }
/// <summary>
/// Returns an UNC path to file system object to work with Windows32 API.
/// </summary>
public string Unc
{
get
{
if (Path.StartsWith(@"\\?\") || Path.StartsWith(@"\\?\UNC\"))
{
return Path;
}
/// <summary>
/// Checks whether the file is readonly or not.
/// </summary>
public bool Readonly
{
get
{
return Exists && (Attributes.HasFlag(FileAttributes.ReadOnly));
}
set
{
if (value)
{
Attributes |= FileAttributes.ReadOnly;
}
else
{
Attributes &= ~FileAttributes.ReadOnly;
}
}
}
/// <summary>
/// Parent file system object.
/// </summary>
public FileSystemObject Parent
{
get
{
if (m_Parent == null)
{
if (Path.Length == 2 && Path[1] == ':') { return null; }
int nameStartIndex = Path.LastIndexOf(Name, StringComparison.OrdinalIgnoreCase);
string parentName = Path.Remove(nameStartIndex).TrimEnd(System.IO.Path.DirectorySeparatorChar);
if (parentName.Length > 0) { m_Parent = new FileSystemObject(parentName, INVALID_FILE_HANDLE); }
}
return m_Parent;
}
}
/// <summary>
/// Checks file system object existence.
/// </summary>
public bool Exists
{
get
{
m_Attributes = GetFileAttributes(Unc);
if (m_Attributes == INVALID_FILE_HANDLE)
{
int errorCode = Marshal.GetLastWin32Error();
if (errorCode != ERROR_SUCCESS &&
errorCode != ERROR_PATH_NOT_FOUND &&
errorCode != ERROR_FILE_NOT_FOUND)
{
throw new Win32Exception(errorCode);
}
}
return m_Attributes != INVALID_FILE_HANDLE;
}
}
/// <summary>
/// True if file system object is file.
/// </summary>
public bool IsFile { get { return Exists && (m_Attributes & (uint)FileAttributes.Directory) == 0; } }
/// <summary>
/// True if file system object is directory.
/// </summary>
public bool IsDirectory { get { return Exists && (m_Attributes & (uint)FileAttributes.Directory) != 0; } }
/// <summary>
/// Returns file system object children.
/// In case of file system object not being a directory, an empty collection will be returned.
/// </summary>
public ReadOnlyCollection<FileSystemObject> Children
{
get
{
ICollection<FileSystemObject> children = GetChildren(SearchAllCriteria, FileSystemObjectSearch.All);
return new ReadOnlyCollection<FileSystemObject>(children.ToList());
}
}
/// <summary>
/// Initialize new file system object.
/// </summary>
/// <param name="path">Physical path.</param>
public FileSystemObject(string path) : this(path, INVALID_FILE_HANDLE) { }
private FileSystemObject(string path, uint attributes)
{
if (path == null) { throw new ArgumentNullException("path"); }
if (path == String.Empty) { throw new ArgumentException("path cannot be empty."); }
// Removes an UNC prefix if there is any..
Path = path.Replace(@"\\?\UNC\", @"\\").Replace(@"\\?\", String.Empty).TrimEnd(System.IO.Path.DirectorySeparatorChar);
m_Attributes = attributes;
}
/// <summary>
/// Removes file system object.
/// </summary>
/// <param name="recursivelyIfDirectory">In case of directory, the content should be deleted as well.</param>
public void Delete(bool recursivelyIfDirectory = false)
{
if (!Exists) { throw new IOException(string.Format("Neither directory nor file {0} exists.", Path)); }
// To avoid additional call to underlying level(local/network storage) we use bitmask to check.
// m_Attributes is already refreshed by calling to Exists property.
if ((m_Attributes & (uint)FileAttributes.Directory) == 0)
{
CheckError(DeleteFile(Unc));
}
else if (!recursivelyIfDirectory)
{
CheckError(RemoveDirectory(Unc));
}
else
{
ICollection<FileSystemObject> children = Children;
children.ForEach(child => child.Delete(true));
CheckError(RemoveDirectory(Unc));
}
}
/// <summary>
/// Checks result and throws Win32Exception.
/// </summary>
/// <param name="result">Result of Win32 operation.</param>
private static void CheckError(bool result)
{
if (!result) { throw new Win32Exception(); }
}
private ICollection<FileSystemObject> GetChildren(string searchPattern, FileSystemObjectSearch fileSystemObjectSearch)
{
if (!IsDirectory) { throw new DirectoryNotFoundException(Path); }
WIN32_FIND_DATA findData;
IntPtr findHandle = FindFirstFile(Unc + @"\" + searchPattern, out findData);
ICollection<FileSystemObject> levelChildren = new List<FileSystemObject>();
try
{
// Add directory separator char to drive.
if (Path.EndsWith(":")) { Path += System.IO.Path.DirectorySeparatorChar; }
for (bool found = (findHandle != INVALID_HANDLE_VALUE); found; found = FindNextFile(findHandle, out findData))
{
var foundFileSystemObject = new FileSystemObject(System.IO.Path.Combine(Unc, findData.cFileName), (uint)findData.dwFileAttributes);
if ((findData.dwFileAttributes & FileAttributes.Directory) != 0)
{
if (findData.cFileName != "." &&
findData.cFileName != ".." &&
fileSystemObjectSearch != FileSystemObjectSearch.FilesOnly)
{
levelChildren.Add(foundFileSystemObject);
}
}
else
{
if (fileSystemObjectSearch != FileSystemObjectSearch.DirectoriesOnly)
{
levelChildren.Add(foundFileSystemObject);
}
}
}
int errorCode = Marshal.GetLastWin32Error();
CheckError(errorCode == ERROR_FILE_NOT_FOUND || errorCode == ERROR_NO_MORE_FILES || errorCode == ERROR_SUCCESS);
}
finally
{
if (findHandle != INVALID_HANDLE_VALUE) { FindClose(findHandle); }
}
return levelChildren;
}
/// <summary>
/// Get all files from current folder including all files from all subfolders.
/// </summary>
/// <returns>Collection of file system objects.</returns>
public ICollection<FileSystemObject> GetFiles()
{
return GetFiles(SearchAllCriteria, SearchOption.TopDirectoryOnly);
}
/// <summary>
/// Get all files from current folder matching the search criteria and in case of
/// searchOption AllDirectories include files from subfolders.
/// </summary>
/// <param name="searchPattern">Search pattern.</param>
/// <param name="searchOption">Search option: TopDirectoryOnly/AllDirectories</param>
/// <returns></returns>
public ICollection<FileSystemObject> GetFiles(string searchPattern, SearchOption searchOption = SearchOption.AllDirectories)
{
if (!IsDirectory) { throw new DirectoryNotFoundException(Path); }
/// <summary>
/// Get whole file structure of specific directory.
/// </summary>
/// <returns></returns>
public ICollection<FileSystemObject> GetFlattenedHierarchy()
{
var resultSet = new List<FileSystemObject>(Children);
var flattenedHierarchy = new List<FileSystemObject>(resultSet);
foreach (var systemObject in flattenedHierarchy.Where(systemObject => systemObject.IsDirectory))
{
resultSet.AddRange(systemObject.GetFlattenedHierarchy());
}
/// <summary>
/// Copy file or directory.
/// </summary>
/// <param name="target">Target file.</param>
/// <param name="overwrite">Overwrite if target file exists.</param>
public void CopyTo(FileSystemObject target, bool overwrite)
{
if (target == null) { throw new ArgumentNullException("target"); }
if (!Exists) { throw new IOException(string.Format("Source {0} does not exists.", Path)); }
// To avoid additional call to underlying level(local/network storage) we use bitmask to check.
// m_Attributes is already refreshed by calling to Exists property.
if ((m_Attributes & (uint)FileAttributes.Directory) == 0)
{
CheckError(CopyFile(Unc, target.IsDirectory ? target.Unc + @"\" + Name : target.Unc, !overwrite));
}
else
{
// Copy directory structure..
var targetSubfolder = new FileSystemObject(target.Unc + @"\" + Name);
if (!targetSubfolder.Exists) { targetSubfolder.CreateDirectory(true); }
ICollection<FileSystemObject> children = Children;
children.ForEach(child => child.CopyTo(targetSubfolder, overwrite));
}
}
/// <summary>
/// Move file or directory.
/// </summary>
/// <param name="target">Target file.</param>
public void MoveTo(FileSystemObject target)
{
if (target == null) { throw new ArgumentNullException("target"); }
if (!Exists) { throw new IOException(string.Format("Source {0} does not exists.", Path)); }
// To avoid additional call to underlying level(local/network storage) we use bitmask to check.
// m_Attributes is already refreshed by calling to Exists property.
if (!MoveFileEx(Unc, target.Unc + @"\" + Name, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
{
int errorCode = Marshal.GetLastWin32Error();
if (errorCode == ERROR_ACCESS_DENIED)
{
// Unable to move folder, use different strategy, moving directory structure manually..
var targetSubfolder = new FileSystemObject(target.Unc + @"\" + Name);
targetSubfolder.CreateDirectory(true);
ICollection<FileSystemObject> children = Children;
children.ForEach(child => child.MoveTo(targetSubfolder));
Delete();
}
else
{
throw new Win32Exception(errorCode);
}
}
}
var targetStream = new FileStream(fileHandle, access);
return targetStream;
}
/// <summary>
/// Read all text from file.
/// </summary>
/// <returns>Returns text content of files.</returns>
public string ReadAllText()
{
using (var reader = new StreamReader(OpenFileStream(FileAccess.Read, FileShare.Read, FileMode.Open)))
{
string fileContent = reader.ReadToEnd();
return fileContent;
}
}
#region Windows API Parameters/Return Values/Error Codes
private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
private static uint INVALID_FILE_HANDLE = uint.MaxValue;
#region Error codes
private const int ERROR_SUCCESS = 0;
private const int ERROR_FILE_NOT_FOUND = 0x2;
private const int ERROR_NO_MORE_FILES = 0x12;
private const int ERROR_ALREADY_EXISTS = 0xB7;
private const int ERROR_PATH_NOT_FOUND = 0x03;
private const int ERROR_ACCESS_DENIED = 0x5;
#endregion //Error codes
#region MoveFileEx flags
private const int MOVEFILE_REPLACE_EXISTING = 0x00000001;
private const int MOVEFILE_COPY_ALLOWED = 0x00000002;
#endregion // MoveFileEx flags
#region Windows Api
/// <summary>
/// WIN32_FIND_DATA
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct WIN32_FIND_DATA
{
public FileAttributes dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public int nFileSizeHigh;
public int nFileSizeLow;
public int dwReserved0;
public int dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternate;
}
Здравствуйте, mDmitriy, Вы писали:
D>Здравствуйте, seimur, Вы писали: S>>Сам совсем недавно решал такую проблему для работы с длинными путями. S>>Тут без WinApi не обойтись. S>>Могу подкинуть если нужно D>Буду благодарен...
namespace System.IO.LongPathExtension
{
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
/// <summary>
/// Usefull extension methods to work with collections.
/// </summary>
public static class CollectionExtension
{
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items)
{
foreach (var item in items)
{
collection.Add(item);
}
}
public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
foreach (var item in collection)
{
action(item);
}
}
}
/// <summary>
///
/// </summary>
public class FileSystemObject
{
private const string SearchAllCriteria = "*";
private uint m_Attributes;
private FileSystemObject m_Parent;
/// <summary>
/// Returns path to file system object.
/// </summary>
public string Path { get; private set; }
/// <summary>
/// Returns an UNC path to file system object to work with Windows32 API.
/// </summary>
public string Unc
{
get
{
if (Path.StartsWith(@"\\?\") || Path.StartsWith(@"\\?\UNC\"))
{
return Path;
}
return (Path.StartsWith(@"\\")) ? @"\\?\UNC\" + (Path.Remove(0, 2)) : @"\\?\" + Path;
}
}
/// <summary>
/// Returns the name of file system object.
/// </summary>
public string Name { get { return System.IO.Path.GetFileName(Path); } }
/// <summary>
/// Returns file attributes.
/// </summary>
private FileAttributes Attributes
{
get { return (FileAttributes)m_Attributes; }
set
{
if (!Exists) { throw new IOException(string.Format("Neither file nor directory {0} is found", Path)); }
if ((FileAttributes)m_Attributes != value)
{
m_Attributes = (uint)value;
CheckError(SetFileAttributes(Unc, m_Attributes));
}
}
}
/// <summary>
/// Checks whether the file is readonly or not.
/// </summary>
public bool Readonly
{
get
{
return Exists && (Attributes.HasFlag(FileAttributes.ReadOnly));
}
set
{
if (value)
{
Attributes |= FileAttributes.ReadOnly;
}
else
{
Attributes &= ~FileAttributes.ReadOnly;
}
}
}
/// <summary>
/// Parent file system object.
/// </summary>
public FileSystemObject Parent
{
get
{
if (m_Parent == null)
{
if (Path.Length == 2 && Path[1] == ':') { return null; }
int nameStartIndex = Path.LastIndexOf(Name, StringComparison.OrdinalIgnoreCase);
string parentName = Path.Remove(nameStartIndex).TrimEnd(System.IO.Path.DirectorySeparatorChar);
if (parentName.Length > 0) { m_Parent = new FileSystemObject(parentName, INVALID_FILE_HANDLE); }
}
return m_Parent;
}
}
/// <summary>
/// Checks file system object existence.
/// </summary>
public bool Exists
{
get
{
m_Attributes = GetFileAttributes(Unc);
if (m_Attributes == INVALID_FILE_HANDLE)
{
int errorCode = Marshal.GetLastWin32Error();
if (errorCode != ERROR_SUCCESS &&
errorCode != ERROR_PATH_NOT_FOUND &&
errorCode != ERROR_FILE_NOT_FOUND)
{
throw new Win32Exception(errorCode);
}
}
return m_Attributes != INVALID_FILE_HANDLE;
}
}
/// <summary>
/// True if file system object is file.
/// </summary>
public bool IsFile { get { return Exists && (m_Attributes & (uint)FileAttributes.Directory) == 0; } }
/// <summary>
/// True if file system object is directory.
/// </summary>
public bool IsDirectory { get { return Exists && (m_Attributes & (uint)FileAttributes.Directory) != 0; } }
/// <summary>
/// Returns file system object children.
/// In case of file system object not being a directory, an empty collection will be returned.
/// </summary>
public ReadOnlyCollection<FileSystemObject> Children
{
get
{
ICollection<FileSystemObject> children = GetChildren(SearchAllCriteria, FileSystemObjectSearch.All);
return new ReadOnlyCollection<FileSystemObject>(children.ToList());
}
}
/// <summary>
/// Initialize new file system object.
/// </summary>
/// <param name="path">Physical path.</param>
public FileSystemObject(string path) : this(path, INVALID_FILE_HANDLE) { }
private FileSystemObject(string path, uint attributes)
{
if (path == null) { throw new ArgumentNullException("path"); }
if (path == String.Empty) { throw new ArgumentException("path cannot be empty."); }
// Removes an UNC prefix if there is any..
Path = path.Replace(@"\\?\UNC\", @"\\").Replace(@"\\?\", String.Empty).TrimEnd(System.IO.Path.DirectorySeparatorChar);
m_Attributes = attributes;
}
/// <summary>
/// Removes file system object.
/// </summary>
/// <param name="recursivelyIfDirectory">In case of directory, the content should be deleted as well.</param>
public void Delete(bool recursivelyIfDirectory = false)
{
if (!Exists) { throw new IOException(string.Format("Neither directory nor file {0} exists.", Path)); }
// To avoid additional call to underlying level(local/network storage) we use bitmask to check.
// m_Attributes is already refreshed by calling to Exists property.
if ((m_Attributes & (uint)FileAttributes.Directory) == 0)
{
CheckError(DeleteFile(Unc));
}
else if (!recursivelyIfDirectory)
{
CheckError(RemoveDirectory(Unc));
}
else
{
ICollection<FileSystemObject> children = Children;
children.ForEach(child => child.Delete(true));
CheckError(RemoveDirectory(Unc));
}
}
/// <summary>
/// Checks result and throws Win32Exception.
/// </summary>
/// <param name="result">Result of Win32 operation.</param>
private static void CheckError(bool result)
{
if (!result) { throw new Win32Exception(); }
}
private ICollection<FileSystemObject> GetChildren(string searchPattern, FileSystemObjectSearch fileSystemObjectSearch)
{
if (!IsDirectory) { throw new DirectoryNotFoundException(Path); }
WIN32_FIND_DATA findData;
IntPtr findHandle = FindFirstFile(Unc + @"\" + searchPattern, out findData);
ICollection<FileSystemObject> levelChildren = new List<FileSystemObject>();
try
{
// Add directory separator char to drive.
if (Path.EndsWith(":")) { Path += System.IO.Path.DirectorySeparatorChar; }
for (bool found = (findHandle != INVALID_HANDLE_VALUE); found; found = FindNextFile(findHandle, out findData))
{
var foundFileSystemObject = new FileSystemObject(System.IO.Path.Combine(Unc, findData.cFileName), (uint)findData.dwFileAttributes);
if ((findData.dwFileAttributes & FileAttributes.Directory) != 0)
{
if (findData.cFileName != "." &&
findData.cFileName != ".." &&
fileSystemObjectSearch != FileSystemObjectSearch.FilesOnly)
{
levelChildren.Add(foundFileSystemObject);
}
}
else
{
if (fileSystemObjectSearch != FileSystemObjectSearch.DirectoriesOnly)
{
levelChildren.Add(foundFileSystemObject);
}
}
}
int errorCode = Marshal.GetLastWin32Error();
CheckError(errorCode == ERROR_FILE_NOT_FOUND || errorCode == ERROR_NO_MORE_FILES || errorCode == ERROR_SUCCESS);
}
finally
{
if (findHandle != INVALID_HANDLE_VALUE) { FindClose(findHandle); }
}
return levelChildren;
}
/// <summary>
/// Get all files from current folder including all files from all subfolders.
/// </summary>
/// <returns>Collection of file system objects.</returns>
public ICollection<FileSystemObject> GetFiles()
{
return GetFiles(SearchAllCriteria, SearchOption.TopDirectoryOnly);
}
/// <summary>
/// Get all files from current folder matching the search criteria and in case of
/// searchOption AllDirectories include files from subfolders.
/// </summary>
/// <param name="searchPattern">Search pattern.</param>
/// <param name="searchOption">Search option: TopDirectoryOnly/AllDirectories</param>
/// <returns></returns>
public ICollection<FileSystemObject> GetFiles(string searchPattern, SearchOption searchOption = SearchOption.AllDirectories)
{
if (!IsDirectory) { throw new DirectoryNotFoundException(Path); }
ICollection<FileSystemObject> files = GetChildren(searchPattern, FileSystemObjectSearch.FilesOnly);
if (searchOption == SearchOption.AllDirectories)
{
ICollection<FileSystemObject> directories = GetChildren(SearchAllCriteria, FileSystemObjectSearch.DirectoriesOnly);
foreach (var directory in directories)
{
files.AddRange(directory.GetFiles(searchPattern, searchOption));
}
}
return files;
}
private static bool CreateDirectoryInternal(string uncPath)
{
return CreateDirectory(uncPath, IntPtr.Zero) || Marshal.GetLastWin32Error() == ERROR_ALREADY_EXISTS;
}
/// <summary>
/// Creates directory.
/// </summary>
/// <param name="recursively"></param>
public void CreateDirectory(bool recursively)
{
if (!CreateDirectoryInternal(Unc))
{
if (Parent == null || !recursively) { throw new Win32Exception(); }
Parent.CreateDirectory(true);
CreateDirectoryInternal(Unc);
}
}
/// <summary>
/// Get whole file structure of specific directory.
/// </summary>
/// <returns></returns>
public ICollection<FileSystemObject> GetFlattenedHierarchy()
{
var resultSet = new List<FileSystemObject>(Children);
var flattenedHierarchy = new List<FileSystemObject>(resultSet);
foreach (var systemObject in flattenedHierarchy.Where(systemObject => systemObject.IsDirectory))
{
resultSet.AddRange(systemObject.GetFlattenedHierarchy());
}
return resultSet;
}
/// <summary>
/// Copy file or directory.
/// </summary>
/// <param name="target">Target file.</param>
/// <param name="overwrite">Overwrite if target file exists.</param>
public void CopyTo(string target, bool overwrite)
{
CopyTo(new FileSystemObject(target), overwrite);
}
/// <summary>
/// Copy file or directory.
/// </summary>
/// <param name="target">Target file.</param>
/// <param name="overwrite">Overwrite if target file exists.</param>
public void CopyTo(FileSystemObject target, bool overwrite)
{
if (target == null) { throw new ArgumentNullException("target"); }
if (!Exists) { throw new IOException(string.Format("Source {0} does not exists.", Path)); }
// To avoid additional call to underlying level(local/network storage) we use bitmask to check.
// m_Attributes is already refreshed by calling to Exists property.
if ((m_Attributes & (uint)FileAttributes.Directory) == 0)
{
CheckError(CopyFile(Unc, target.IsDirectory ? target.Unc + @"\" + Name : target.Unc, !overwrite));
}
else
{
// Copy directory structure..
var targetSubfolder = new FileSystemObject(target.Unc + @"\" + Name);
if (!targetSubfolder.Exists) { targetSubfolder.CreateDirectory(true); }
ICollection<FileSystemObject> children = Children;
children.ForEach(child => child.CopyTo(targetSubfolder, overwrite));
}
}
/// <summary>
/// Move file or directory.
/// </summary>
/// <param name="target">Target file.</param>
public void MoveTo(string target)
{
MoveTo(new FileSystemObject(target));
}
/// <summary>
/// Move file or directory.
/// </summary>
/// <param name="target">Target file.</param>
public void MoveTo(FileSystemObject target)
{
if (target == null) { throw new ArgumentNullException("target"); }
if (!Exists) { throw new IOException(string.Format("Source {0} does not exists.", Path)); }
// To avoid additional call to underlying level(local/network storage) we use bitmask to check.
// m_Attributes is already refreshed by calling to Exists property.
if (!MoveFileEx(Unc, target.Unc + @"\" + Name, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
{
int errorCode = Marshal.GetLastWin32Error();
if (errorCode == ERROR_ACCESS_DENIED)
{
// Unable to move folder, use different strategy, moving directory structure manually..
var targetSubfolder = new FileSystemObject(target.Unc + @"\" + Name);
targetSubfolder.CreateDirectory(true);
ICollection<FileSystemObject> children = Children;
children.ForEach(child => child.MoveTo(targetSubfolder));
Delete();
}
else
{
throw new Win32Exception(errorCode);
}
}
}
/// <summary>
/// File access
/// </summary>
[Flags]
public enum WinApiFileAccess : uint
{
/// <summary>
/// GenericRead
/// </summary>
GenericRead = 0x80000000,
/// <summary>
/// GenericWrite
/// </summary>
GenericWrite = 0x40000000,
/// <summary>
/// GenericExecute
/// </summary>
GenericExecute = 0x20000000,
/// <summary>
/// GenericAll
/// </summary>
GenericAll = 0x10000000,
}
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern SafeFileHandle CreateFile(
string lpFileName,
WinApiFileAccess dwDesiredAccess,
FileShare dwShareMode,
IntPtr lpSecurityAttributes,
FileMode dwCreationDisposition,
FileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile);
/// <summary>
/// Openes file stream regarding to specified parameters.
/// </summary>
/// <param name="access">File access.</param>
/// <param name="share">File share.</param>
/// <param name="mode">Creation disposition.</param>
/// <returns>Returns opened stream.</returns>
public Stream OpenFileStream(FileAccess access, FileShare share, FileMode mode)
{
return OpenFileStream(Unc, access, share, mode);
}
/// <summary>
/// Openes file stream regarding to specified parameters.
/// </summary>
/// <param name="file">Path to file.</param>
/// <param name="access">File access.</param>
/// <param name="share">File share.</param>
/// <param name="mode">Creation disposition.</param>
/// <returns>Returns opened stream.</returns>
public static Stream OpenFileStream(string file, FileAccess access, FileShare share, FileMode mode)
{
SafeFileHandle fileHandle = CreateFile(file, ConvertFileAccessValue(access), share, IntPtr.Zero, mode, 0, IntPtr.Zero);
CheckError(!fileHandle.IsInvalid);
var targetStream = new FileStream(fileHandle, access);
return targetStream;
}
/// <summary>
/// Read all text from file.
/// </summary>
/// <returns>Returns text content of files.</returns>
public string ReadAllText()
{
using (var reader = new StreamReader(OpenFileStream(FileAccess.Read, FileShare.Read, FileMode.Open)))
{
string fileContent = reader.ReadToEnd();
return fileContent;
}
}
private static WinApiFileAccess ConvertFileAccessValue(FileAccess access)
{
switch (access)
{
case FileAccess.Read:
return WinApiFileAccess.GenericRead;
case FileAccess.Write:
return WinApiFileAccess.GenericWrite;
}
return WinApiFileAccess.GenericRead | WinApiFileAccess.GenericWrite;
}
#region Windows API Parameters/Return Values/Error Codes
private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
private static uint INVALID_FILE_HANDLE = uint.MaxValue;
#region Error codes
private const int ERROR_SUCCESS = 0;
private const int ERROR_FILE_NOT_FOUND = 0x2;
private const int ERROR_NO_MORE_FILES = 0x12;
private const int ERROR_ALREADY_EXISTS = 0xB7;
private const int ERROR_PATH_NOT_FOUND = 0x03;
private const int ERROR_ACCESS_DENIED = 0x5;
#endregion //Error codes
#region MoveFileEx flags
private const int MOVEFILE_REPLACE_EXISTING = 0x00000001;
private const int MOVEFILE_COPY_ALLOWED = 0x00000002;
#endregion // MoveFileEx flags
#region Windows Api
/// <summary>
/// WIN32_FIND_DATA
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct WIN32_FIND_DATA
{
public FileAttributes dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public int nFileSizeHigh;
public int nFileSizeLow;
public int dwReserved0;
public int dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternate;
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FindClose(IntPtr hFindFile);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeleteFile(string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool RemoveDirectory(string lpFileName);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, int dwFlags);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CopyFile(string lpExistingFileName, string lpNewFileName, bool failIfExists);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CreateDirectory(string lpPathName, IntPtr lpSecurityAttributes);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern uint GetFileAttributes(string directoryPath);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool SetFileAttributes(string lpFileName, uint dwFileAttributes);
#endregion //Windows Api
#endregion //Windows API Parameters/Return Values/Error Codes
}
enum FileSystemObjectSearch { FilesOnly, DirectoriesOnly, All }
}
Теоретически нет разницы между теорией и практикой, но на практике она есть
Re[2]: Как создать файл по пути длиной более 256 символов?
Здравствуйте, Vladek, Вы писали:
V>Здравствуйте, mDmitriy, Вы писали:
D>>Путь outputPath состоит из десятка подкаталогов, но общая длина более 256 символов D>>Как быть?
V>Надо в начале пути добавить "\\?\" и всё вроде бы должно заработать.
.NET не умеет работать с UNC путями, тут без WinAPI не обойтись либо использовать какие нибудь сторонние библиотеки если есть
Теоретически нет разницы между теорией и практикой, но на практике она есть
Re: Как создать файл по пути длиной более 256 символов?