/// <summary> /// Copy a file to a project relative path. /// </summary> /// <param name="projectHierarchy"> /// The project where to add the file. /// </param> /// <param name="fileName"> /// The path to the file to copy. /// </param> /// <param name="targetPath"> /// The target path, including the filename. /// </param> /// <param name="addFileOptions"> /// The options to use while coping the file. /// </param> private async Task AddFileToProjectInFolder(IVsHierarchy projectHierarchy, string fileName, string targetPath, AddFileOptions addFileOptions) { targetPath = AzureIoTHubConnectedServiceHandlerHelper.GetProjectRelativePath(projectHierarchy, targetPath); Project project = ConnectedServicesUtilities.GetDteProject(projectHierarchy); ProjectItems items = project.ProjectItems; fileName = await this.CopyFileAsync(fileName, targetPath); string fileToAdd = ConnectedServicesUtilities.GetProjectFullPath(projectHierarchy, targetPath); string targetFileName = Path.GetFileName(fileToAdd); // Build the directory structure if it doesn't already exist. Directory.CreateDirectory(Path.GetDirectoryName(fileToAdd)); // clone the AdditionalReplacementValues dictionary so we aren't modifying the original Dictionary <string, string> replacementValues = new Dictionary <string, string>(addFileOptions.AdditionalReplacementValues); ProjectItem item = AzureIoTHubConnectedServiceHandlerHelper.GetNestedProjectItem(items, targetPath); bool existOnDisk = File.Exists(fileToAdd); if (item == null && existOnDisk) { // The file is not in the project. We should add the file. // This is some arbitrary file, which we'll update in the same // path as existing project files. // This is 'fileToAdd' because we're not adding the final file here. item = items.AddFromFile(fileToAdd); } if (item != null) { // Add the folder-specific RootNamespace replacement value so $RootNamespace$ has the folder structure in it for C# projects this.AddRootNamespaceReplacementValue(replacementValues, item.Collection); bool filesEqual = this.AreFilesEqualWithReplacement(item, fileName, replacementValues); if (!filesEqual) { if (!addFileOptions.SuppressOverwritePrompt && !this.PromptOverwrite(targetFileName)) { // The user chose not to overwrite the file, so abort adding this file. return; } // Get the document and overwrite with file content. BufferUtilities.UpdateProjectItemFromFile(item, fileName); } } else { File.Copy(fileName, fileToAdd); item = items.AddFromFile(fileToAdd); // Add the folder-specific RootNamespace replacement value so $RootNamespace$ has the folder structure in it for C# projects this.AddRootNamespaceReplacementValue(replacementValues, item.Collection); } this.PerformTokenReplacement(item, replacementValues); if (addFileOptions.OpenOnComplete && !item.IsOpen) { try { var window = item.Open(); // Ensure that the window is always shown regardless of "Preview" // user settings. if (window != null && !window.Visible) { window.Visible = true; } } catch (Exception) { } } }