/// <summary> /// Move item within the project from one location to where it already exists, skipping the move. /// </summary> private void MoveDuplicateFileNameSkipMove(MoveDelegate mover) { foreach (var projectType in ProjectTypes) { var testDef = new ProjectDefinition("MoveDuplicateFileName", projectType, ItemGroup( Folder("Folder"), Content("textfile.txt", "root"), Content("Folder\\textfile.txt", "Folder") ) ); using (var solution = testDef.Generate().ToVs()) { mover( solution.FindItem("MoveDuplicateFileName", "Folder"), solution.FindItem("MoveDuplicateFileName", "textfile.txt") ); using (var dialog = OverwriteFileDialog.Wait(solution.App)) { dialog.No(); } solution.App.WaitForDialogDismissed(); solution.AssertFileExistsWithContent("root", "MoveDuplicateFileName", "textfile.txt"); solution.AssertFileExistsWithContent("Folder", "MoveDuplicateFileName", "Folder", "textfile.txt"); } } }
public static OverwriteFileDialog Wait(VisualStudioApp app) { var hwnd = app.WaitForDialog(); Assert.AreNotEqual(IntPtr.Zero, hwnd, "Did not find OverwriteFileDialog"); var element = AutomationElement.FromHandle(hwnd); try { Assert.IsNotNull(element.FindFirst( TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "_allItems") ), "Not correct dialog - missing '_allItems'"); Assert.IsNotNull(element.FindFirst( TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "_yes") ), "Not correct dialog - missing '_yes'"); OverwriteFileDialog res = new OverwriteFileDialog(app, element); element = null; return(res); } finally { if (element != null) { AutomationWrapper.DumpElement(element); } } }
/// <summary> /// Cut 2 items, paste where they exist, skip pasting the 1st one but paste the 2nd. /// /// The 1st item shouldn't be removed from the parent hierarchy, the 2nd should, and only the 2nd item should be overwritten. /// </summary> private void MoveDuplicateFileNamesCrossProjectSkipOne(MoveDelegate mover) { foreach (var projectType in ProjectTypes) { var projectDefs = new[] { new ProjectDefinition("MoveDuplicateFileName", projectType, ItemGroup( Content("textfile1.txt", "textfile1 - lang"), Content("textfile2.txt", "textfile2 - lang") ) ), new ProjectDefinition("MoveDuplicateFileName2", projectType, ItemGroup( Folder("Folder"), Content("textfile1.txt", "textfile1 - 2"), Content("textfile2.txt", "textfile2 - 2") ) ) }; using (var solution = SolutionFile.Generate("MoveDuplicateFileName", projectDefs).ToVs()) { var item1 = solution.FindItem("MoveDuplicateFileName", "textfile1.txt"); var item2 = solution.FindItem("MoveDuplicateFileName", "textfile2.txt"); mover( solution.FindItem("MoveDuplicateFileName2"), item1, item2 ); using (var dialog = OverwriteFileDialog.Wait(solution.App)) { dialog.No(); } System.Threading.Thread.Sleep(1000); using (var dialog = OverwriteFileDialog.Wait(solution.App)) { dialog.Yes(); } solution.App.WaitForDialogDismissed(); solution.AssertFileExistsWithContent("textfile1 - lang", "MoveDuplicateFileName", "textfile1.txt"); solution.AssertFileExistsWithContent("textfile2 - lang", "MoveDuplicateFileName", "textfile2.txt"); solution.AssertFileExistsWithContent("textfile1 - 2", "MoveDuplicateFileName2", "textfile1.txt"); solution.AssertFileExistsWithContent("textfile2 - lang", "MoveDuplicateFileName2", "textfile2.txt"); } } }
/// <summary> /// Cut 2 items, paste where they exist, skip pasting the 1st one but paste the 2nd. /// /// The 1st item shouldn't be removed from the parent hierarchy, the 2nd should, and only the 2nd item should be overwritten. /// </summary> private void MoveDuplicateFileNamesFoldersSkipOne(MoveDelegate mover) { foreach (var projectType in ProjectTypes) { var testDef = new ProjectDefinition("MoveDuplicateFileName", projectType, ItemGroup( Folder("Source"), Content("Source\\textfile1.txt", "source1"), Content("Source\\textfile2.txt", "source2"), Folder("Target"), Content("Target\\textfile1.txt", "target1"), Content("Target\\textfile2.txt", "target2") ) ); using (var solution = testDef.Generate().ToVs()) { mover( solution.FindItem("MoveDuplicateFileName", "Target"), solution.FindItem("MoveDuplicateFileName", "Source", "textfile1.txt"), solution.FindItem("MoveDuplicateFileName", "Source", "textfile2.txt") ); using (var dialog = OverwriteFileDialog.Wait(solution.App)) { dialog.No(); } System.Threading.Thread.Sleep(1000); using (var dialog = OverwriteFileDialog.Wait(solution.App)) { dialog.Yes(); } solution.App.WaitForDialogDismissed(); solution.AssertFileExistsWithContent("source1", "MoveDuplicateFileName", "Source", "textfile1.txt"); solution.AssertFileDoesntExist("MoveDuplicateFileName", "textfile2.txt"); solution.AssertFileExistsWithContent("target1", "MoveDuplicateFileName", "Target", "textfile1.txt"); solution.AssertFileExistsWithContent("source2", "MoveDuplicateFileName", "Target", "textfile2.txt"); } } }
//backup files public static void BackupFiles(string sFolderPath) { var dontAskAgain = false; var yesNo = false; var deleteBackups = false; var iStep = 0; RefreshInfo(sFolderPath, false, false); MainForm.Log_WriteLine("-----"); MainForm.Log_WriteLine("Starting backup of " + backupList.Count + " files"); MainForm.Log_WriteLine("-----"); foreach (var s in backupList) { var sBackupFile = s.Replace(".ddsified", ""); var sDDSToDelete = Path.ChangeExtension(sBackupFile, "dds"); if (File.Exists(sDDSToDelete)) { File.Delete(sDDSToDelete); } if (File.Exists(sBackupFile)) { if (!dontAskAgain) { var dialog = new OverwriteFileDialog(); yesNo = (dialog.CustomShowDialog(sBackupFile, out dontAskAgain, ref deleteBackups) == DialogResult.Yes); } if (yesNo) { File.Delete(sBackupFile); File.Move(s, sBackupFile); MainForm.Log_WriteLine("Reverting " + sDDSToDelete + " to " + sBackupFile); } else { if (deleteBackups) { File.Delete(s); } MainForm.Log_WriteLine("Skipping backup of " + sBackupFile); } } else { File.Move(s, sBackupFile); MainForm.Log_WriteLine("Reverting " + sDDSToDelete + " to " + sBackupFile); } iStep += 1; MainForm.ReportProgress(Convert.ToInt32((iStep / backupList.Count) * 100), "Reverting " + Path.GetFileName(sBackupFile) + ", file " + iStep + "\\" + backupList.Count); MainForm.Log_WriteLine("---"); Application.DoEvents(); } MainForm.Log_WriteLine("-----"); MainForm.Log_WriteLine("Backup done! " + backupList.Count + " files processed."); MainForm.Log_WriteLine("-----"); }
/// <summary> /// Tests to see if we can add the folder to the project. Returns true if it's ok, false if it's not. /// </summary> /// <param name="folderToAdd">Project reference (from data object) using the format: {Guid}|project|folderPath</param> /// <param name="targetNode">Node to add the new folder to</param> private Addition CanAddFolderFromProjectReference(string folderToAdd) { Utilities.ArgumentNotNullOrEmpty(folderToAdd, "folderToAdd"); var targetFolderNode = TargetNode.GetDragTargetHandlerNode(); string folder; IVsHierarchy sourceHierarchy; GetPathAndHierarchy(folderToAdd, out folder, out sourceHierarchy); // Ensure we don't end up in an endless recursion if (Utilities.IsSameComObject(Project, sourceHierarchy)) { if (String.Equals(folder, targetFolderNode.FullPathToChildren, StringComparison.OrdinalIgnoreCase)) { if (DropEffect == DropEffect.Move && IsBadMove(targetFolderNode.FullPathToChildren, folder, false)) { return null; } } if (targetFolderNode.FullPathToChildren.StartsWith(folder, StringComparison.OrdinalIgnoreCase) && !String.Equals(targetFolderNode.FullPathToChildren, folder, StringComparison.OrdinalIgnoreCase)) { // dragging a folder into a child, that's not allowed Utilities.ShowMessageBox( Project.Site, SR.GetString(SR.CannotMoveIntoSubfolder, CommonUtils.GetFileOrDirectoryName(folder)), null, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return null; } } var targetPath = Path.Combine(targetFolderNode.FullPathToChildren, CommonUtils.GetFileOrDirectoryName(folder)); if (File.Exists(targetPath)) { Utilities.ShowMessageBox( Project.Site, SR.GetString(SR.CannotAddFileExists, CommonUtils.GetFileOrDirectoryName(folder)), null, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return null; } if (Directory.Exists(targetPath)) { if (DropEffect == DropEffect.Move) { if (targetPath == folderToAdd) { CannotMoveSameLocation(folderToAdd); } else { Utilities.ShowMessageBox( Project.Site, SR.GetString(SR.CannotMoveFolderExists, CommonUtils.GetFileOrDirectoryName(folder)), null, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); } return null; } var dialog = new OverwriteFileDialog( SR.GetString(SR.OverwriteFilesInExistingFolder, CommonUtils.GetFileOrDirectoryName(folder)), false ); dialog.Owner = Application.Current.MainWindow; var res = dialog.ShowDialog(); if (res == null) { // cancel, abort the whole copy return null; } else if (!dialog.ShouldOverwrite) { // no, don't copy the folder return SkipOverwriteAddition.Instance; } // otherwise yes, and we'll prompt about the files. } string targetFileName = CommonUtils.GetFileOrDirectoryName(folder); if (Utilities.IsSameComObject(Project, sourceHierarchy) && String.Equals(targetFolderNode.FullPathToChildren, folder, StringComparison.OrdinalIgnoreCase)) { // copying a folder onto its self, make a copy targetFileName = GetCopyName(targetFolderNode.FullPathToChildren); } List<Addition> additions = new List<Addition>(); uint folderId; if (ErrorHandler.Failed(sourceHierarchy.ParseCanonicalName(folder, out folderId))) { // the folder may have been deleted between the copy & paste ReportMissingItem(folder); return null; } if (Path.Combine(targetFolderNode.FullPathToChildren, targetFileName).Length >= NativeMethods.MAX_FOLDER_PATH) { Utilities.ShowMessageBox( Project.Site, SR.GetString(SR.FolderPathTooLongShortMessage), null, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return null; } if (!WalkSourceProjectAndAdd(sourceHierarchy, folderId, targetFolderNode.FullPathToChildren, false, additions, targetFileName)) { return null; } if (additions.Count == 1) { return (FolderAddition)additions[0]; } Debug.Assert(additions.Count == 0); return null; }
/// <summary> /// Prompts if the file should be overwriten. Returns false if the user cancels, true if the user answered yes/no /// </summary> /// <param name="filename"></param> /// <param name="dialog"></param> /// <returns></returns> private static bool PromptOverwriteFile(string filename, out OverwriteFileDialog dialog) { dialog = new OverwriteFileDialog(SR.GetString(SR.FileAlreadyExists, Path.GetFileName(filename)), true); dialog.Owner = Application.Current.MainWindow; bool? dialogResult = dialog.ShowDialog(); if (dialogResult != null && !dialogResult.Value) { // user cancelled return false; } return true; }
/// <summary> /// Adds an item from a project refererence to target node. /// </summary> /// <param name="projectRef"></param> /// <param name="targetNode"></param> private Addition CanAddFileFromProjectReference(string projectRef, string targetFolder, bool fromFolder = false) { Utilities.ArgumentNotNullOrEmpty("projectRef", projectRef); IVsSolution solution = Project.GetService(typeof(IVsSolution)) as IVsSolution; Utilities.CheckNotNull(solution); uint itemidLoc; IVsHierarchy hierarchy; string str; VSUPDATEPROJREFREASON[] reason = new VSUPDATEPROJREFREASON[1]; if (ErrorHandler.Failed(solution.GetItemOfProjref(projectRef, out hierarchy, out itemidLoc, out str, reason))) { // the file may have been deleted between the copy & paste string path; Guid projectGuid; GetPathAndProjectId(projectRef, out projectGuid, out path); ReportMissingItem(path); return null; } Utilities.CheckNotNull(hierarchy); // This will throw invalid cast exception if the hierrachy is not a project. IVsProject project = (IVsProject)hierarchy; string moniker; ErrorHandler.ThrowOnFailure(project.GetMkDocument(itemidLoc, out moniker)); if (DropEffect == DropEffect.Move && IsBadMove(targetFolder, moniker, true)) { return null; } if (!File.Exists(moniker)) { VsShellUtilities.ShowMessageBox( Project.Site, String.Format("The item '{0}' does not exist in the project directory. It may have been moved, renamed or deleted.", Path.GetFileName(moniker)), null, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return null; } string newPath = Path.Combine(targetFolder, Path.GetFileName(moniker)); var existingChild = Project.FindNodeByFullPath(moniker); if (existingChild != null && existingChild.IsLinkFile) { if (DropEffect == DropEffect.Move) { // moving a link file, just update it's location in the hierarchy return new ReparentLinkedFileAddition(Project, targetFolder, moniker); } else { // VsShellUtilities.ShowMessageBox( Project.Site, String.Format("Cannot copy linked files within the same project. You cannot have more than one link to the same file in a project."), null, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return null; } } else if (File.Exists(newPath) && CommonUtils.IsSamePath(newPath, moniker)) { newPath = GetCopyName(newPath); } bool ok = false; if (DropEffect == DropEffect.Move && Utilities.IsSameComObject(project, Project)) { ok = Project.Tracker.CanRenameItem(moniker, newPath, VSRENAMEFILEFLAGS.VSRENAMEFILEFLAGS_NoFlags); } else { ok = Project.Tracker.CanAddItems( new[] { newPath }, new VSQUERYADDFILEFLAGS[] { VSQUERYADDFILEFLAGS.VSQUERYADDFILEFLAGS_NoFlags }); } if (ok) { if (File.Exists(newPath)) { if (DropEffect == DropEffect.Move && Utilities.IsSameComObject(project, Project) && Project.FindNodeByFullPath(newPath) != null) { // if we're overwriting an item, we're moving it, make sure that's ok. // OverwriteFileAddition will handle the remove from the hierarchy if (!Project.Tracker.CanRemoveItems(new[] { newPath }, new[] { VSQUERYREMOVEFILEFLAGS.VSQUERYREMOVEFILEFLAGS_NoFlags })) { return null; } } bool? overwrite = OverwriteAllItems; if (overwrite == null) { var dialog = new OverwriteFileDialog(String.Format("A file with the name '{0}' already exists. Do you want to replace it?", Path.GetFileName(moniker)), true); dialog.Owner = Application.Current.MainWindow; bool? dialogResult = dialog.ShowDialog(); if (dialogResult != null && !dialogResult.Value) { // user cancelled return null; } overwrite = dialog.ShouldOverwrite; if (dialog.AllItems) { OverwriteAllItems = overwrite; } } if (overwrite.Value) { return new OverwriteFileAddition(Project, targetFolder, DropEffect, moniker, Path.GetFileName(newPath), project); } else { return NopAddition.Instance; } } if (newPath.Length >= NativeMethods.MAX_PATH) { VsShellUtilities.ShowMessageBox( Project.Site, "The filename is too long.", null, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return null; } return new FileAddition(Project, targetFolder, DropEffect, moniker, Path.GetFileName(newPath), project); } return null; }
/// <summary> /// Tests to see if we can add the folder to the project. Returns true if it's ok, false if it's not. /// </summary> /// <param name="folderToAdd">Project reference (from data object) using the format: {Guid}|project|folderPath</param> /// <param name="targetNode">Node to add the new folder to</param> private Addition CanAddFolderFromProjectReference(string folderToAdd) { Utilities.ArgumentNotNullOrEmpty(folderToAdd, "folderToAdd"); var targetFolderNode = TargetNode.GetDragTargetHandlerNode(); string folder; IVsHierarchy sourceHierarchy; GetPathAndHierarchy(folderToAdd, out folder, out sourceHierarchy); // Ensure we don't end up in an endless recursion if (Utilities.IsSameComObject(Project, sourceHierarchy)) { if (String.Equals(folder, targetFolderNode.FullPathToChildren, StringComparison.OrdinalIgnoreCase)) { if (DropEffect == DropEffect.Move && IsBadMove(targetFolderNode.FullPathToChildren, folder, false)) { return null; } } if (targetFolderNode.FullPathToChildren.StartsWith(folder, StringComparison.OrdinalIgnoreCase) && !String.Equals(targetFolderNode.FullPathToChildren, folder, StringComparison.OrdinalIgnoreCase)) { // dragging a folder into a child, that's not allowed VsShellUtilities.ShowMessageBox( Project.Site, String.Format("Cannot move '{0}'. The destination folder is a subfolder of the source folder.", Path.GetFileName(CommonUtils.TrimEndSeparator(folder))), null, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return null; } } var targetPath = Path.Combine(targetFolderNode.FullPathToChildren, Path.GetFileName(CommonUtils.TrimEndSeparator(folder))); if (File.Exists(targetPath)) { VsShellUtilities.ShowMessageBox( Project.Site, String.Format("Unable to add '{0}'. A file with that name already exists.", Path.GetFileName(CommonUtils.TrimEndSeparator(folder))), null, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return null; } if (Directory.Exists(targetPath)) { if (DropEffect == DropEffect.Move) { if (targetPath == folderToAdd) { CannotMoveSameLocation(folderToAdd); } else { VsShellUtilities.ShowMessageBox( Project.Site, String.Format("Cannot move the folder '{0}'. A folder with that name already exists in the destination directory.", Path.GetFileName(CommonUtils.TrimEndSeparator(folder))), null, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); } return null; } var dialog = new OverwriteFileDialog(String.Format( @"This folder already contains a folder called '{0}' If the files in the existing folder have the same names as files in the folder you are copying, do you want to replace the existing files?", Path.GetFileName(CommonUtils.TrimEndSeparator(folder))), false); dialog.Owner = Application.Current.MainWindow; var res = dialog.ShowDialog(); if (res == null) { // cancel, abort the whole copy return null; } else if (!dialog.ShouldOverwrite) { // no, don't copy the folder return NopAddition.Instance; } // otherwise yes, and we'll prompt about the files. } string targetFileName = Path.GetFileName(CommonUtils.TrimEndSeparator(folder)); if (Utilities.IsSameComObject(Project, sourceHierarchy) && String.Equals(targetFolderNode.FullPathToChildren, folder, StringComparison.OrdinalIgnoreCase)) { // copying a folder onto its self, make a copy targetFileName = GetCopyName(targetFolderNode.FullPathToChildren); } List<Addition> additions = new List<Addition>(); uint folderId; if (ErrorHandler.Failed(sourceHierarchy.ParseCanonicalName(folder, out folderId))) { // the folder may have been deleted between the copy & paste ReportMissingItem(folder); return null; } if (Path.Combine(targetFolderNode.FullPathToChildren, targetFileName).Length >= NativeMethods.MAX_FOLDER_PATH) { VsShellUtilities.ShowMessageBox( Project.Site, "The folder name is too long.", null, OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return null; } if (!WalkSourceProjectAndAdd(sourceHierarchy, folderId, targetFolderNode.FullPathToChildren, false, additions, targetFileName)) { return null; } if (additions.Count == 1) { return (FolderAddition)additions[0]; } Debug.Assert(additions.Count == 0); return null; }