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