public async Task<bool> AddNodeJSScript(string containerDirectory, 
            string scriptFile = null, bool? invokeAfter = null)
        {
            if (!(await EnsureProjectHasNodeJSEnabled())) return false;
            _logger.LogInfo("Begin adding NodeJS script");
            invokeAfter = invokeAfter ?? true;
            if (string.IsNullOrWhiteSpace(containerDirectory))
                containerDirectory = Project.GetDirectory();

            if (string.IsNullOrWhiteSpace(scriptFile))
            {
                _logger.LogInfo("Prompting for file name");
                var dialog = new AddBuildScriptNamePrompt(containerDirectory, ".js");
                // dialog.InvokeAfter = false;
                var dialogResult = dialog.ShowDialog(VsEnvironment.OwnerWindow);
                if (dialogResult == DialogResult.Cancel) return false;
                scriptFile = dialog.FileName;
                _logger.LogInfo("File name chosen: " + scriptFile);
                invokeAfter = dialog.InvokeAfter;
                _logger.LogInfo("Selected invoke sequence: Invoke" + (dialog.InvokeAfter ? "After" : "Before") + " (..the build)");
            }
            var scriptFileName = scriptFile;
            if (!scriptFile.Contains(":") && !scriptFile.StartsWith("\\\\"))
                scriptFile = Path.Combine(containerDirectory, scriptFile);

            if (Project == null) return false;

            File.WriteAllText(scriptFile, @"(function() {

    // MSBuild project properties are exposed at build-time. Example:
    console.log(""msbuild.properties['ProjectGuid'] = \"""" + msbuild.properties['ProjectGuid'] + ""\"""");

    // Example: gulp
    //   (run appropriate npm install commands from this directory first)
    //
    // var gulp = require('gulp'),
    //     gutil = require('gulp-util');
    // gulp.task('default', function () {
    //     return gutil.log('Gulp is running!')
    // });
    // gulp.start('default');


})();");
            var addedItem = Project.ProjectItems.AddFromFile(scriptFile);
            addedItem.Properties.Item("ItemType").Value
                = invokeAfter.Value ? "InvokeAfter" : "InvokeBefore";
            _logger.LogInfo("NodeJS script added to project: " + scriptFileName);
            Task.Run(() =>
            {
                System.Threading.Thread.Sleep(250);
                _dte.ExecuteCommand("File.OpenFile", "\"" + scriptFile + "\"");
            });
            return true;
        }
        public async Task<bool> AddPowerShellScript(string containerDirectory, 
            string scriptFile = null, bool? invokeAfter = null)
        {
            if (!(await EnsureProjectHasPowerShellEnabled())) return false;
            _logger.LogInfo("Begin adding PowerShell script");
            invokeAfter = invokeAfter ?? true;
            if (string.IsNullOrWhiteSpace(containerDirectory))
                containerDirectory = Project.GetDirectory();

            if (string.IsNullOrWhiteSpace(scriptFile))
            {
                _logger.LogInfo("Prompting for file name");
                var dialog = new AddBuildScriptNamePrompt(containerDirectory, ".ps1");
                var dialogResult = dialog.ShowDialog(VsEnvironment.OwnerWindow);
                if (dialogResult == DialogResult.Cancel) return false;
                scriptFile = dialog.FileName;
                _logger.LogInfo("File name chosen: " + scriptFile);
                invokeAfter = dialog.InvokeAfter;
                _logger.LogInfo("Selected invoke sequence: Invoke" + (dialog.InvokeAfter ? "After" : "Before") + " (..the build)");
            }
            var scriptFileName = scriptFile;
            if (!scriptFile.Contains(":") && !scriptFile.StartsWith("\\\\"))
                scriptFile = Path.Combine(containerDirectory, scriptFile);

            if (Project == null) return false;

            File.WriteAllText(scriptFile, @"# MSBuild project properties are exposed at build-time. Example:
Write-Output ""`$MSBuildProjectDirectory = `""$MSBuildProjectDirectory`""""");
            var addedItem = Project.ProjectItems.AddFromFile(scriptFile);
            addedItem.Properties.Item("ItemType").Value
                = invokeAfter.Value ? "InvokeAfter" : "InvokeBefore";
            _logger.LogInfo("PowerShell script added to project: " + scriptFileName);
            await Task.Run(() =>
            {
                System.Threading.Thread.Sleep(250);
                _dte.ExecuteCommand("File.OpenFile", "\"" + scriptFile + "\"");
            });
            return true;
        }
        public async Task<bool> AddProjectInclude(string containerDirectory, string scriptFile = null)
        {
            if (!Project.Saved)
            {
                var saveDialogResult = MessageBox.Show(_ownerWindow, "Save pending changes to solution?",
                    "Save pending changes", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (saveDialogResult == DialogResult.OK || saveDialogResult == DialogResult.Yes)
                    _dte.SaveAll();
            }
            if (!Project.Saved || string.IsNullOrEmpty(Project.FullName))
            {
                var saveDialogResult = MessageBox.Show(_ownerWindow, "Pending changes need to be saved. Please save the project before adding project imports, then retry.", "Save first",
                    MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk);
                if (saveDialogResult != DialogResult.Cancel) _dte.SaveAll();
                return false;
            }
            _logger.LogInfo("Begin adding project import file");
            if (string.IsNullOrWhiteSpace(containerDirectory))
                containerDirectory = Project.GetDirectory();

            if (string.IsNullOrWhiteSpace(scriptFile))
            {
                _logger.LogInfo("Prompting for file name");
                var dialog = new AddBuildScriptNamePrompt(containerDirectory, ".targets")
                {
                    HideInvokeBeforeAfter = true
                };
                var dialogResult = dialog.ShowDialog(VsEnvironment.OwnerWindow);
                if (dialogResult == DialogResult.Cancel) return false;
                scriptFile = dialog.FileName;
                _logger.LogInfo("File name chosen: " + scriptFile);
                dialogResult = MessageBox.Show(_ownerWindow, @"        !! IMPORTANT !!

You must not move, rename, or remove this file once it has been added to the project. By adding this file you are extending the project file itself. If you must change the filename or location, you must update the project XML directly where <Import> references it.",
                    "This addition is permanent", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                if (dialogResult == DialogResult.Cancel) return false;
            }
            var scriptFileName = scriptFile;
            if (!scriptFile.Contains(":") && !scriptFile.StartsWith("\\\\"))
                scriptFile = Path.Combine(containerDirectory, scriptFile);
            var scriptFileRelativePath = FileUtilities.GetRelativePath(Project.GetDirectory(), scriptFile);
            var scriptFileShortName = new FileInfo(scriptFile).Name;
            if (scriptFileShortName.Contains("."))
                scriptFileShortName = scriptFileShortName.Substring(0, scriptFileShortName.LastIndexOf("."));

            if (Project == null) return false;

            File.WriteAllText(scriptFile, @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
    <Target Name=""" + scriptFileShortName + @"""><!-- consider adding attrib BeforeTargets=""Build"" or AfterTargets=""Build"" -->

        <!-- my tasks here -->
        <Message Importance=""high"" Text=""" + scriptFileShortName + @".targets output: ProjectGuid = $(ProjectGuid)"" />

    </Target>
</Project>");
            var projRoot = Project.GetProjectRoot();
            var import = projRoot.AddImport(scriptFileRelativePath);
            import.Condition = "Exists('" + scriptFileRelativePath + "')";
            Project = await Project.SaveProjectRoot();
            var addedItem = Project.ProjectItems.AddFromFile(scriptFile);
            addedItem.Properties.Item("ItemType").Value = "None";
            _logger.LogInfo("Project include file added to project: " + scriptFileName);
            Task.Run(() =>
            {
                System.Threading.Thread.Sleep(250);
                _dte.ExecuteCommand("File.OpenFile", "\"" + scriptFile + "\"");
            });
            return true;
        }