Пример #1
0
 public override IAsyncAction DeleteAsync()
 {
     return(AsyncInfo.Run(async(cancellationToken) =>
     {
         if (!NativeFileOperationsHelper.DeleteFileFromApp(Path))
         {
             throw new Win32Exception(Marshal.GetLastWin32Error());
         }
     }));
 }
Пример #2
0
 public static void WriteFileTag(string filePath, string tag)
 {
     if (tag == null)
     {
         NativeFileOperationsHelper.DeleteFileFromApp($"{filePath}:files");
     }
     else if (ReadFileTag(filePath) != tag)
     {
         NativeFileOperationsHelper.WriteStringToFile($"{filePath}:files", tag);
     }
 }
Пример #3
0
        public static void WriteFileTag(string filePath, string tag)
        {
            var isReadOnly = NativeFileOperationsHelper.HasFileAttribute(filePath, System.IO.FileAttributes.ReadOnly);

            if (isReadOnly) // Unset read-only attribute (#7534)
            {
                NativeFileOperationsHelper.UnsetFileAttribute(filePath, System.IO.FileAttributes.ReadOnly);
            }
            if (tag == null)
            {
                NativeFileOperationsHelper.DeleteFileFromApp($"{filePath}:files");
            }
            else if (ReadFileTag(filePath) != tag)
            {
                NativeFileOperationsHelper.WriteStringToFile($"{filePath}:files", tag);
            }
            if (isReadOnly) // Restore read-only attribute (#7534)
            {
                NativeFileOperationsHelper.SetFileAttribute(filePath, System.IO.FileAttributes.ReadOnly);
            }
        }
Пример #4
0
        public async Task <IStorageHistory> DeleteAsync(IStorageItemWithPath source,
                                                        IProgress <float> progress,
                                                        IProgress <FileSystemStatusCode> errorCode,
                                                        bool permanently,
                                                        CancellationToken cancellationToken)
        {
            bool deleteFromRecycleBin = recycleBinHelpers.IsPathUnderRecycleBin(source.Path);

            FilesystemResult fsResult = FileSystemStatusCode.InProgress;

            errorCode?.Report(fsResult);
            progress?.Report(0.0f);

            if (permanently)
            {
                fsResult = (FilesystemResult)NativeFileOperationsHelper.DeleteFileFromApp(source.Path);
            }
            if (!fsResult)
            {
                if (source.ItemType == FilesystemItemType.File)
                {
                    fsResult = await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(source.Path)
                               .OnSuccess((t) => t.DeleteAsync(permanently ? StorageDeleteOption.PermanentDelete : StorageDeleteOption.Default).AsTask());
                }
                else if (source.ItemType == FilesystemItemType.Directory)
                {
                    fsResult = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(source.Path)
                               .OnSuccess((t) => t.DeleteAsync(permanently ? StorageDeleteOption.PermanentDelete : StorageDeleteOption.Default).AsTask());
                }
            }

            errorCode?.Report(fsResult);

            if (fsResult == FileSystemStatusCode.Unauthorized)
            {
                // Try again with fulltrust process (non admin: for shortcuts and hidden files)
                if (associatedInstance.ServiceConnection != null)
                {
                    var(status, response) = await associatedInstance.ServiceConnection.SendMessageForResponseAsync(new ValueSet()
                    {
                        { "Arguments", "FileOperation" },
                        { "fileop", "DeleteItem" },
                        { "filepath", source.Path },
                        { "permanently", permanently }
                    });

                    fsResult = (FilesystemResult)(status == AppServiceResponseStatus.Success &&
                                                  response.Get("Success", false));
                }
                if (!fsResult)
                {
                    fsResult = await PerformAdminOperation(new ValueSet()
                    {
                        { "Arguments", "FileOperation" },
                        { "fileop", "DeleteItem" },
                        { "filepath", source.Path },
                        { "permanently", permanently }
                    });
                }
            }
            else if (fsResult == FileSystemStatusCode.InUse)
            {
                // TODO: retry or show dialog
                await DialogDisplayHelper.ShowDialogAsync("FileInUseDeleteDialog/Title".GetLocalized(), "FileInUseDeleteDialog/Text".GetLocalized());
            }

            if (deleteFromRecycleBin)
            {
                // Recycle bin also stores a file starting with $I for each item
                string iFilePath = Path.Combine(Path.GetDirectoryName(source.Path), Path.GetFileName(source.Path).Replace("$R", "$I"));
                await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(iFilePath)
                .OnSuccess(t => t.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask());
            }
            errorCode?.Report(fsResult);
            progress?.Report(100.0f);

            if (fsResult)
            {
                await associatedInstance.FilesystemViewModel.RemoveFileOrFolderAsync(source.Path);

                if (!permanently)
                {
                    // Enumerate Recycle Bin
                    List <ShellFileItem> items = await recycleBinHelpers.EnumerateRecycleBin();

                    List <ShellFileItem> nameMatchItems = new List <ShellFileItem>();

                    // Get name matching files
                    if (items != null)
                    {
                        if (Path.GetExtension(source.Path) == ".lnk" || Path.GetExtension(source.Path) == ".url") // We need to check if it is a shortcut file
                        {
                            nameMatchItems = items.Where((item) => item.FilePath == Path.Combine(Path.GetDirectoryName(source.Path), Path.GetFileNameWithoutExtension(source.Path))).ToList();
                        }
                        else
                        {
                            nameMatchItems = items.Where((item) => item.FilePath == source.Path).ToList();
                        }
                    }

                    // Get newest file
                    ShellFileItem item = nameMatchItems.Where((item) => item.RecycleDate != null).OrderBy((item) => item.RecycleDate).FirstOrDefault();

                    return(new StorageHistory(FileOperationType.Recycle, source, StorageItemHelpers.FromPathAndType(item?.RecyclePath, source.ItemType)));
                }

                return(new StorageHistory(FileOperationType.Delete, source, null));
            }
            else
            {
                // Stop at first error
                return(null);
            }
        }
Пример #5
0
        private async Task PasteItemAsync(DataPackageView packageView, string destinationPath, DataPackageOperation acceptedOperation, IShellPage AppInstance, IProgress <uint> progress)
        {
            if (!packageView.Contains(StandardDataFormats.StorageItems))
            {
                // Happens if you copy some text and then you Ctrl+V in FilesUWP
                // Should this be done in ModernShellPage?
                return;
            }

            IReadOnlyList <IStorageItem> itemsToPaste = await packageView.GetStorageItemsAsync();

            if (AppInstance.FilesystemViewModel.WorkingDirectory.StartsWith(App.AppSettings.RecycleBinPath))
            {
                // Do not paste files and folders inside the recycle bin
                await DialogDisplayHelper.ShowDialogAsync("ErrorDialogThisActionCannotBeDone".GetLocalized(), "ErrorDialogUnsupportedOperation".GetLocalized());

                return;
            }

            List <IStorageItem>    pastedSourceItems = new List <IStorageItem>();
            HashSet <IStorageItem> pastedItems       = new HashSet <IStorageItem>();
            var  totalItemsSize       = CalculateTotalItemsSize(itemsToPaste);
            bool isItemSizeUnreported = totalItemsSize <= 0;

            foreach (IStorageItem item in itemsToPaste)
            {
                if (item.IsOfType(StorageItemTypes.Folder))
                {
                    if (!string.IsNullOrEmpty(item.Path) && destinationPath.IsSubPathOf(item.Path))
                    {
                        ImpossibleActionResponseTypes responseType = ImpossibleActionResponseTypes.Abort;

                        /// Currently following implementation throws exception until it is resolved keep it disabled

                        /*Binding themeBind = new Binding();
                         * themeBind.Source = ThemeHelper.RootTheme;
                         *
                         * ContentDialog dialog = new ContentDialog()
                         * {
                         *  Title = ResourceController.GetTranslation("ErrorDialogThisActionCannotBeDone"),
                         *  Content = ResourceController.GetTranslation("ErrorDialogTheDestinationFolder") + " (" + destinationPath.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries).Last() + ") " + ResourceController.GetTranslation("ErrorDialogIsASubfolder") + " (" + item.Name + ")",
                         *  PrimaryButtonText = ResourceController.GetTranslation("ErrorDialogSkip"),
                         *  CloseButtonText = ResourceController.GetTranslation("ErrorDialogCancel"),
                         *  PrimaryButtonCommand = new RelayCommand(() => { responseType = ImpossibleActionResponseTypes.Skip; }),
                         *  CloseButtonCommand = new RelayCommand(() => { responseType = ImpossibleActionResponseTypes.Abort; }),
                         * };
                         * BindingOperations.SetBinding(dialog, FrameworkElement.RequestedThemeProperty, themeBind);
                         *
                         * await dialog.ShowAsync();*/
                        if (responseType == ImpossibleActionResponseTypes.Skip)
                        {
                            continue;
                        }
                        else if (responseType == ImpossibleActionResponseTypes.Abort)
                        {
                            return;
                        }
                    }
                    else
                    {
                        if (!isItemSizeUnreported)
                        {
                            var pastedItemSize = await Task.Run(() => CalculateTotalItemsSize(pastedSourceItems));

                            uint progressValue = (uint)(pastedItemSize * 100 / totalItemsSize);
                            progress.Report(progressValue);
                        }

                        await AppInstance.FilesystemViewModel.GetFolderFromPathAsync(destinationPath)
                        .OnSuccess(t => CloneDirectoryAsync((StorageFolder)item, t, item.Name))
                        .OnSuccess(t =>
                        {
                            pastedSourceItems.Add(item);
                            pastedItems.Add(t);
                        });
                    }
                }
                else if (item.IsOfType(StorageItemTypes.File))
                {
                    if (!isItemSizeUnreported)
                    {
                        var pastedItemSize = await Task.Run(() => CalculateTotalItemsSize(pastedSourceItems));

                        uint progressValue = (uint)(pastedItemSize * 100 / totalItemsSize);
                        progress.Report(progressValue);
                    }

                    var res = await AppInstance.FilesystemViewModel.GetFolderFromPathAsync(destinationPath);

                    if (res)
                    {
                        StorageFile clipboardFile = (StorageFile)item;
                        var         pasted        = await FilesystemTasks.Wrap(() => clipboardFile.CopyAsync(res.Result, item.Name, NameCollisionOption.GenerateUniqueName).AsTask());

                        if (pasted)
                        {
                            pastedSourceItems.Add(item);
                            pastedItems.Add(pasted.Result);
                        }
                        else if (pasted.ErrorCode == FilesystemErrorCode.ERROR_UNAUTHORIZED)
                        {
                            // Try again with CopyFileFromApp
                            if (NativeFileOperationsHelper.CopyFileFromApp(item.Path, Path.Combine(destinationPath, item.Name), true))
                            {
                                pastedSourceItems.Add(item);
                            }
                            else
                            {
                                Debug.WriteLine(System.Runtime.InteropServices.Marshal.GetLastWin32Error());
                            }
                        }
                        else if (pasted.ErrorCode == FilesystemErrorCode.ERROR_NOTFOUND)
                        {
                            // File was moved/deleted in the meantime
                            continue;
                        }
                    }
                }
            }
            if (!isItemSizeUnreported)
            {
                var finalPastedItemSize = await Task.Run(() => CalculateTotalItemsSize(pastedSourceItems));

                uint finalProgressValue = (uint)(finalPastedItemSize * 100 / totalItemsSize);
                progress.Report(finalProgressValue);
            }
            else
            {
                progress.Report(100);
            }

            if (acceptedOperation == DataPackageOperation.Move)
            {
                foreach (IStorageItem item in pastedSourceItems)
                {
                    var deleted = (FilesystemResult)false;
                    if (string.IsNullOrEmpty(item.Path))
                    {
                        // Can't move (only copy) files from MTP devices because:
                        // StorageItems returned in DataPackageView are read-only
                        // The item.Path property will be empty and there's no way of retrieving a new StorageItem with R/W access
                        continue;
                    }
                    if (item.IsOfType(StorageItemTypes.File))
                    {
                        // If we reached this we are not in an MTP device, using StorageFile.* is ok here
                        deleted = await AppInstance.FilesystemViewModel.GetFileFromPathAsync(item.Path)
                                  .OnSuccess(t => t.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask());
                    }
                    else if (item.IsOfType(StorageItemTypes.Folder))
                    {
                        // If we reached this we are not in an MTP device, using StorageFolder.* is ok here
                        deleted = await AppInstance.FilesystemViewModel.GetFolderFromPathAsync(item.Path)
                                  .OnSuccess(t => t.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask());
                    }

                    if (deleted == FilesystemErrorCode.ERROR_UNAUTHORIZED)
                    {
                        // Try again with DeleteFileFromApp
                        if (!NativeFileOperationsHelper.DeleteFileFromApp(item.Path))
                        {
                            Debug.WriteLine(System.Runtime.InteropServices.Marshal.GetLastWin32Error());
                        }
                    }
                    else if (deleted == FilesystemErrorCode.ERROR_NOTFOUND)
                    {
                        // File or Folder was moved/deleted in the meantime
                        continue;
                    }
                }
            }

            if (destinationPath == AppInstance.FilesystemViewModel.WorkingDirectory)
            {
                List <string>     pastedItemPaths = pastedItems.Select(item => item.Path).ToList();
                List <ListedItem> copiedItems     = AppInstance.FilesystemViewModel.FilesAndFolders.Where(listedItem => pastedItemPaths.Contains(listedItem.ItemPath)).ToList();
                if (copiedItems.Any())
                {
                    AppInstance.ContentPage.SetSelectedItemsOnUi(copiedItems);
                    AppInstance.ContentPage.FocusSelectedItems();
                }
            }
            packageView.ReportOperationCompleted(acceptedOperation);
        }
Пример #6
0
        private async Task <FilesystemResult> DeleteItemAsync(StorageDeleteOption deleteOption, IShellPage AppInstance, IProgress <uint> progress)
        {
            var deleted = (FilesystemResult)false;
            var deleteFromRecycleBin = AppInstance.FilesystemViewModel.WorkingDirectory.StartsWith(App.AppSettings.RecycleBinPath);

            List <ListedItem> selectedItems = new List <ListedItem>();

            foreach (ListedItem selectedItem in AppInstance.ContentPage.SelectedItems)
            {
                selectedItems.Add(selectedItem);
            }

            if (App.AppSettings.ShowConfirmDeleteDialog == true) //check if the setting to show a confirmation dialog is on
            {
                var dialog = new ConfirmDeleteDialog(deleteFromRecycleBin, deleteOption, AppInstance.ContentPage.SelectedItemsPropertiesViewModel);
                await dialog.ShowAsync();

                if (dialog.Result != MyResult.Delete) //delete selected  item(s) if the result is yes
                {
                    return((FilesystemResult)true);   //return if the result isn't delete
                }
                deleteOption = dialog.PermanentlyDelete;
            }

            int itemsDeleted = 0;

            foreach (ListedItem storItem in selectedItems)
            {
                uint progressValue = (uint)(itemsDeleted * 100.0 / selectedItems.Count);
                if (selectedItems.Count > 3)
                {
                    progress.Report(progressValue);
                }

                if (storItem.PrimaryItemAttribute == StorageItemTypes.File)
                {
                    deleted = await AppInstance.FilesystemViewModel.GetFileFromPathAsync(storItem.ItemPath)
                              .OnSuccess(t => t.DeleteAsync(deleteOption).AsTask());
                }
                else
                {
                    deleted = await AppInstance.FilesystemViewModel.GetFolderFromPathAsync(storItem.ItemPath)
                              .OnSuccess(t => t.DeleteAsync(deleteOption).AsTask());
                }

                if (deleted.ErrorCode == FilesystemErrorCode.ERROR_UNAUTHORIZED)
                {
                    if (deleteOption == StorageDeleteOption.Default)
                    {
                        // Try again with fulltrust process
                        if (AppInstance.FilesystemViewModel.Connection != null)
                        {
                            var response = await AppInstance.FilesystemViewModel.Connection.SendMessageAsync(new ValueSet()
                            {
                                { "Arguments", "FileOperation" },
                                { "fileop", "MoveToBin" },
                                { "filepath", storItem.ItemPath }
                            });

                            deleted = (FilesystemResult)(response.Status == Windows.ApplicationModel.AppService.AppServiceResponseStatus.Success);
                        }
                    }
                    else
                    {
                        // Try again with DeleteFileFromApp
                        if (!NativeFileOperationsHelper.DeleteFileFromApp(storItem.ItemPath))
                        {
                            Debug.WriteLine(System.Runtime.InteropServices.Marshal.GetLastWin32Error());
                        }
                        else
                        {
                            deleted = (FilesystemResult)true;
                        }
                    }
                }
                else if (deleted.ErrorCode == FilesystemErrorCode.ERROR_INUSE)
                {
                    // TODO: retry or show dialog
                    await DialogDisplayHelper.ShowDialogAsync("FileInUseDeleteDialog/Title".GetLocalized(), "FileInUseDeleteDialog/Text".GetLocalized());
                }

                if (deleteFromRecycleBin)
                {
                    // Recycle bin also stores a file starting with $I for each item
                    var iFilePath = Path.Combine(Path.GetDirectoryName(storItem.ItemPath), Path.GetFileName(storItem.ItemPath).Replace("$R", "$I"));
                    await AppInstance.FilesystemViewModel.GetFileFromPathAsync(iFilePath)
                    .OnSuccess(t => t.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask());
                }

                if (deleted)
                {
                    await AppInstance.FilesystemViewModel.RemoveFileOrFolderAsync(storItem);

                    itemsDeleted++;
                }
                else
                {
                    // Stop at first error
                    return(deleted);
                }
            }
            return((FilesystemResult)true);
        }