private void AddProjectFolder(string name, NewItemTarget target) { // Make sure the directory exists before we add it to the project. Don't // use `PackageUtilities.EnsureOutputPath()` because it can silently fail. Directory.CreateDirectory(Path.Combine(target.Directory, name)); // We can't just add the final directory to the project because that will // only add the final segment rather than adding each segment in the path. // Split the name into segments and add each folder individually. ProjectItems items = target.ProjectItem?.ProjectItems ?? target.Project.ProjectItems; string parentDirectory = target.Directory; foreach (string segment in SplitPath(name)) { parentDirectory = Path.Combine(parentDirectory, segment); // Look for an existing folder in case it's already in the project. ProjectItem folder = items .OfType <ProjectItem>() .Where(item => segment.Equals(item.Name, StringComparison.OrdinalIgnoreCase)) .Where(item => item.IsKind(Constants.vsProjectItemKindPhysicalFolder, Constants.vsProjectItemKindVirtualFolder)) .FirstOrDefault(); if (folder == null) { folder = items.AddFromDirectory(parentDirectory); } items = folder.ProjectItems; } }
private async void ExecuteAsync(object sender, EventArgs e) { NewItemTarget target = NewItemTarget.Create(_dte); if (target == null) { MessageBox.Show( "Could not determine where to create the new file. Select a file or folder in Solution Explorer and try again.", Vsix.Name, MessageBoxButton.OK, MessageBoxImage.Error); return; } string input = PromptForFileName(target.Directory).TrimStart('/', '\\').Replace("/", "\\"); if (string.IsNullOrEmpty(input)) { return; } string[] parsedInputs = GetParsedInput(input); foreach (string name in parsedInputs) { try { await AddItemAsync(name, target); } catch (PathTooLongException ex) { MessageBox.Show("The file name is too long 😢", Vsix.Name, MessageBoxButton.OK, MessageBoxImage.Error); Logger.Log(ex); } catch (Exception ex) { Logger.Log(ex); MessageBox.Show( $"Error creating file '{name}':{Environment.NewLine}{ex.Message}", Vsix.Name, MessageBoxButton.OK, MessageBoxImage.Error); } } }
private async System.Threading.Tasks.Task AddItemAsync(string name, NewItemTarget target) { if (name.EndsWith("\\", StringComparison.Ordinal)) { if (target.IsSolutionOrSolutionFolder) { GetOrAddSolutionFolder(name, target); } else { AddProjectFolder(name, target); } } else { await AddFileAsync(name, target); } }
public static NewItemTarget Create(DTE2 dte) { NewItemTarget item = null; // If a document is active, try to use the document's containing directory. if (dte.ActiveWindow is Window2 window && window.Type == vsWindowType.vsWindowTypeDocument) { item = CreateFromActiveDocument(dte); } // If no document was selected, or we could not get a selected item from // the document, then use the selected item in the Solution Explorer window. if (item == null) { item = CreateFromSolutionExplorerSelection(dte); } return(item); }
private Project GetOrAddSolutionFolder(string name, NewItemTarget target) { if (target.IsSolution && string.IsNullOrEmpty(name)) { // An empty solution folder name means we are not creating any solution // folders for that item, and the file we are adding is intended to be // added to the solution. Files cannot be added directly to the solution, // so there is a "Solution Items" folder that they are added to. return(_dte.Solution.FindSolutionFolder(SolutionItemsProjectName) ?? ((Solution2)_dte.Solution).AddSolutionFolder(SolutionItemsProjectName)); } // Even though solution folders are always virtual, if the target directory exists, // then we will also create the new directory on disk. This ensures that any files // that are added to this folder will end up in the corresponding physical directory. if (Directory.Exists(target.Directory)) { // Don't use `PackageUtilities.EnsureOutputPath()` because it can silently fail. Directory.CreateDirectory(Path.Combine(target.Directory, name)); } Project parent = target.Project; foreach (string segment in SplitPath(name)) { // If we don't have a parent project yet, // then this folder is added to the solution. if (parent == null) { parent = _dte.Solution.FindSolutionFolder(segment) ?? ((Solution2)_dte.Solution).AddSolutionFolder(segment); } else { parent = parent.FindSolutionFolder(segment) ?? ((SolutionFolder)parent.Object).AddSolutionFolder(segment); } } return(parent); }
private async System.Threading.Tasks.Task AddItemAsync(string name, NewItemTarget target) { // The naming rules that apply to files created on disk also apply to virtual solution folders, // so regardless of what type of item we are creating, we need to validate the name. ValidatePath(name); if (name.EndsWith("\\", StringComparison.Ordinal)) { if (target.IsSolutionOrSolutionFolder) { GetOrAddSolutionFolder(name, target); } else { AddProjectFolder(name, target); } } else { await AddFileAsync(name, target); } }
private async System.Threading.Tasks.Task AddFileAsync(string name, NewItemTarget target) { FileInfo file; // If the file is being added to a solution folder, but that // solution folder doesn't have a corresponding directory on // disk, then write the file to the root of the solution instead. if (target.IsSolutionFolder && !Directory.Exists(target.Directory)) { file = new FileInfo(Path.Combine(Path.GetDirectoryName(_dte.Solution.FullName), Path.GetFileName(name))); } else { file = new FileInfo(Path.Combine(target.Directory, name)); } // Make sure the directory exists before we create the file. Don't use // `PackageUtilities.EnsureOutputPath()` because it can silently fail. Directory.CreateDirectory(file.DirectoryName); if (!file.Exists) { Project project; if (target.IsSolutionOrSolutionFolder) { project = GetOrAddSolutionFolder(Path.GetDirectoryName(name), target); } else { project = target.Project; } int position = await WriteFileAsync(project, file.FullName); if (target.ProjectItem != null && target.ProjectItem.IsKind(Constants.vsProjectItemKindVirtualFolder)) { target.ProjectItem.ProjectItems.AddFromFile(file.FullName); } else { project.AddFileToProject(file); } VsShellUtilities.OpenDocument(this, file.FullName); // Move cursor into position. if (position > 0) { Microsoft.VisualStudio.Text.Editor.IWpfTextView view = ProjectHelpers.GetCurentTextView(); if (view != null) { view.Caret.MoveTo(new SnapshotPoint(view.TextBuffer.CurrentSnapshot, position)); } } ExecuteCommandIfAvailable("SolutionExplorer.SyncWithActiveDocument"); _dte.ActiveDocument.Activate(); } else { MessageBox.Show($"The file '{file}' already exists.", Vsix.Name, MessageBoxButton.OK, MessageBoxImage.Information); } }