private async Task MoveDirectoryAsync(string sourceFullPath, string destFullPath) { StorageFolder sourceFolder = await StorageFolder.GetFolderFromPathAsync(sourceFullPath).TranslateWinRTTask(sourceFullPath, isDirectory: true); // WinRT doesn't support move, only rename // If parents are the same, just rename. string sourceParent, sourceFolderName, destParent, destFolderName; PathHelpers.SplitDirectoryFile(sourceFullPath, out sourceParent, out sourceFolderName); PathHelpers.SplitDirectoryFile(destFullPath, out destParent, out destFolderName); // same parent folder if (String.Equals(sourceParent, destParent, StringComparison.OrdinalIgnoreCase)) { // not the same subfolder if (!String.Equals(sourceFolderName, destFolderName, StringComparison.OrdinalIgnoreCase)) { await sourceFolder.RenameAsync(destFolderName).TranslateWinRTTask(destFullPath, isDirectory: true); } // else : nothing to do } else { // Otherwise, create the destination and move each item recursively. // We could do a copy, which would be safer in case of a failure // We do a move because it has the perf characteristics that match the win32 move StorageFolder destFolder = await CreateDirectoryAsync(destFullPath, failIfExists : true).ConfigureAwait(false); await MoveDirectoryAsync(sourceFolder, destFolder).ConfigureAwait(false); } }
private async Task <StorageFolder> CreateDirectoryAsync(string fullPath, bool failIfExists) { if (fullPath.Length >= Interop.Kernel32.MAX_DIRECTORY_PATH) { throw new PathTooLongException(SR.IO_PathTooLong); } Stack <string> stackDir = new Stack <string>(); StorageFolder workingFolder = null; string workingPath = fullPath; // walk up the path until we can get a directory while (workingFolder == null) { try { workingFolder = await StorageFolder.GetFolderFromPathAsync(workingPath).TranslateWinRTTask(workingPath, isDirectory: true); } catch (IOException) { } catch (UnauthorizedAccessException) { } if (workingFolder == null) { // we couldn't get the directory, we'll need to create it string folderName = null; PathHelpers.SplitDirectoryFile(workingPath, out workingPath, out folderName); if (String.IsNullOrEmpty(folderName)) { // we reached the root and it did not exist. we can't create roots. throw Win32Marshal.GetExceptionForWin32Error(Interop.Errors.ERROR_PATH_NOT_FOUND, workingPath); } stackDir.Push(folderName); Debug.Assert(!String.IsNullOrEmpty(workingPath)); } } Debug.Assert(workingFolder != null); if (failIfExists && (stackDir.Count == 0)) { throw Win32Marshal.GetExceptionForWin32Error(Interop.Errors.ERROR_ALREADY_EXISTS, fullPath); } // we have work to do. if stackDir is empty it means we were passed a path to an existing directory. while (stackDir.Count > 0) { // use CreationCollisionOption.OpenIfExists to address a race conditions when creating directories workingFolder = await workingFolder.CreateFolderAsync(stackDir.Pop(), CreationCollisionOption.OpenIfExists).TranslateWinRTTask(fullPath, isDirectory: true); } return(workingFolder); }
private async Task CopyFileAsync(string sourceFullPath, string destFullPath, bool overwrite) { StorageFile file = await StorageFile.GetFileFromPathAsync(sourceFullPath).TranslateWinRTTask(sourceFullPath); string destDirectory, destFileName; PathHelpers.SplitDirectoryFile(destFullPath, out destDirectory, out destFileName); StorageFolder destFolder = await StorageFolder.GetFolderFromPathAsync(destDirectory).TranslateWinRTTask(destDirectory, isDirectory: true); await file.CopyAsync(destFolder, destFileName, overwrite?NameCollisionOption.ReplaceExisting : NameCollisionOption.FailIfExists).TranslateWinRTTask(sourceFullPath); }
private static async Task <IStorageItem> GetStorageItemAsync(string fullPath) { string directoryPath, itemName; PathHelpers.SplitDirectoryFile(fullPath, out directoryPath, out itemName); StorageFolder parent = await StorageFolder.GetFolderFromPathAsync(directoryPath).TranslateWinRTTask(directoryPath, isDirectory: true); if (String.IsNullOrEmpty(itemName)) { return(parent); } return(await parent.GetItemAsync(itemName).TranslateWinRTTask(fullPath)); }
private async Task <bool> DirectoryExistsAsync(string fullPath) { string directoryPath = null, fileName = null; PathHelpers.SplitDirectoryFile(fullPath, out directoryPath, out fileName); // Rather than call await StorageFolder.GetFolderFromPathAsync(fullPath); and catch FileNotFoundException // we try to avoid the exception by calling TryGetItemAsync. // We can still hit an exception if the parent directory doesn't exist but it does provide better performance // for the existing parent/non-existing directory case and avoids a first chance exception which is a developer // pain point. StorageFolder parent = null; try { parent = await StorageFolder.GetFolderFromPathAsync(directoryPath).TranslateWinRTTask(directoryPath, isDirectory: true); } catch (IOException) { } catch (UnauthorizedAccessException) { } if (String.IsNullOrEmpty(fileName)) { // we were given a root return(parent != null); } if (parent != null) { StorageFolder folder = await parent.TryGetItemAsync(fileName).TranslateWinRTTask(fullPath, isDirectory: true) as StorageFolder; return(folder != null); } else { // it's possible we don't have access to the parent but do have access to this folder try { StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(fullPath).TranslateWinRTTask(fullPath, isDirectory: true); return(folder != null); } catch (IOException) { } catch (UnauthorizedAccessException) { } } return(false); }
private async Task <bool> FileExistsAsync(string fullPath) { string directoryPath = null, fileName = null; PathHelpers.SplitDirectoryFile(fullPath, out directoryPath, out fileName); if (String.IsNullOrEmpty(fileName)) { // No filename was provided return(false); } // Rather than call await StorageFile.GetFileFromPathAsync(fullPath); and catch FileNotFoundException // we try to avoid the exception by calling TryGetItemAsync. // We can still hit an exception if the directory doesn't exist but it does provide better performance // for the existing folder/non-existing file case and avoids a first chance exception which is a developer // pain point. StorageFolder parent = null; try { parent = await StorageFolder.GetFolderFromPathAsync(directoryPath).TranslateWinRTTask(directoryPath); } catch (IOException) { } catch (UnauthorizedAccessException) { } StorageFile file = null; if (parent != null) { // The expectation is that this API will never throw, thus it is missing TranslateWinRTTask file = await parent.TryGetItemAsync(fileName).TranslateWinRTTask(fullPath) as StorageFile; } else { // it's possible we don't have access to the parent but do have access to this file try { file = await StorageFile.GetFileFromPathAsync(fullPath).TranslateWinRTTask(fullPath); } catch (IOException) { } catch (UnauthorizedAccessException) { } } return((file != null) ? file.IsAvailable : false); }
private async Task MoveFileAsync(string sourceFullPath, string destFullPath) { StorageFile file = await StorageFile.GetFileFromPathAsync(sourceFullPath).TranslateWinRTTask(sourceFullPath); string destDirectory, destFileName; PathHelpers.SplitDirectoryFile(destFullPath, out destDirectory, out destFileName); // Win32 MoveFileEx will return success if source and destination are the same. // Comparison is safe here as the caller has normalized both paths. if (!sourceFullPath.Equals(destFullPath, StringComparison.OrdinalIgnoreCase)) { StorageFolder destFolder = await StorageFolder.GetFolderFromPathAsync(destDirectory).TranslateWinRTTask(destDirectory, isDirectory: true); await file.MoveAsync(destFolder, destFileName, NameCollisionOption.FailIfExists).TranslateWinRTTask(sourceFullPath); } }
// Similar to WinRTFileSystem.TryGetStorageItemAsync but we only // want to capture exceptions that are not related to file not // found. This matches the behavior of the Win32 implementation. private async Task RefreshAsync() { string directoryPath, itemName; _item = null; _initializationException = null; try { PathHelpers.SplitDirectoryFile(_fullPath, out directoryPath, out itemName); StorageFolder parent = null; try { parent = await StorageFolder.GetFolderFromPathAsync(directoryPath).TranslateWinRTTask(directoryPath, isDirectory: true); } catch (DirectoryNotFoundException) { // Ignore DirectoryNotFound, in this case we just return null; } if (String.IsNullOrEmpty(itemName) || null == parent) { _item = parent; } else { _item = await parent.TryGetItemAsync(itemName).TranslateWinRTTask(_fullPath); } } catch (Exception e) { _initializationException = ExceptionDispatchInfo.Capture(e); } }
private async Task <FileStreamBase> OpenAsync(string fullPath, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, FileStream parent) { // When trying to open the root directory, we need to throw an Access Denied if (PathInternal.GetRootLength(fullPath) == fullPath.Length) { throw Win32Marshal.GetExceptionForWin32Error(Interop.Errors.ERROR_ACCESS_DENIED, fullPath); } // Win32 CreateFile returns ERROR_PATH_NOT_FOUND when given a path that ends with '\' if (PathHelpers.EndsInDirectorySeparator(fullPath)) { throw Win32Marshal.GetExceptionForWin32Error(Interop.Errors.ERROR_PATH_NOT_FOUND, fullPath); } StorageFile file = null; // FileMode if (mode == FileMode.Open || mode == FileMode.Truncate) { file = await StorageFile.GetFileFromPathAsync(fullPath).TranslateWinRTTask(fullPath); } else { CreationCollisionOption collisionOptions; switch (mode) { case FileMode.Create: collisionOptions = CreationCollisionOption.ReplaceExisting; break; case FileMode.CreateNew: collisionOptions = CreationCollisionOption.FailIfExists; break; case FileMode.Append: case FileMode.OpenOrCreate: default: collisionOptions = CreationCollisionOption.OpenIfExists; break; } string directoryPath, fileName; PathHelpers.SplitDirectoryFile(fullPath, out directoryPath, out fileName); StorageFolder directory = await StorageFolder.GetFolderFromPathAsync(directoryPath).TranslateWinRTTask(directoryPath, isDirectory: true); file = await directory.CreateFileAsync(fileName, collisionOptions).TranslateWinRTTask(fullPath); } // FileAccess: WinRT doesn't support FileAccessMode.Write so we upgrade to ReadWrite FileAccessMode accessMode = ((access & FileAccess.Write) != 0) ? FileAccessMode.ReadWrite : FileAccessMode.Read; // FileShare: cannot translate StorageFile uses a different sharing model (oplocks) that is controlled via FileAccessMode // FileOptions: ignore most values of FileOptions as they are hints and are not supported by WinRT. // FileOptions.Encrypted is not a hint, and not supported by WinRT, but there is precedent for ignoring this (FAT). // FileOptions.DeleteOnClose should result in an UnauthorizedAccessException when // opening a file that can only be read, but we cannot safely reproduce that behavior // in WinRT without actually deleting the file. // Instead the failure will occur in the finalizer for WinRTFileStream and be ignored. // open our stream Stream stream = (await file.OpenAsync(accessMode).TranslateWinRTTask(fullPath)).AsStream(bufferSize); if (mode == FileMode.Append) { // seek to end. stream.Seek(0, SeekOrigin.End); } else if (mode == FileMode.Truncate) { // truncate stream to 0 stream.SetLength(0); } return(new WinRTFileStream(stream, file, access, options, parent)); }