/// <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)
                {
                }
            }
        }
        private bool AreFilesEqualWithReplacement(ProjectItem item, string fileName, IDictionary <string, string> additionalReplacementValues)
        {
            TokenReplacementBuilder tokenReplacement = this.BuildTokenReplacement(additionalReplacementValues);

            return(BufferUtilities.AreFilesEqual(item, fileName, tokenReplacement));
        }