/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Management.Automation; using Pwsh = System.Management.Automation.PowerShell; namespace Microsoft.Rest.ClientRuntime.PowerShell { internal static class PsHelpers { public static IEnumerable RunScript(string script) => Pwsh.Create().AddScript(script).Invoke(); public static void RunScript(string script) => RunScript(script); public static IEnumerable RunScript(CommandInvocationIntrinsics cii, string script) => cii.InvokeScript(script).Select(o => o?.BaseObject).Where(o => o != null).OfType(); public static void RunScript(CommandInvocationIntrinsics cii, string script) => RunScript(cii, script); public static IEnumerable GetModuleCmdlets(PSCmdlet cmdlet, params string[] modulePaths) { var getCmdletsCommand = String.Join(" + ", modulePaths.Select(mp => $"(Get-Command -Module (Import-Module '{mp}' -PassThru))")); return (cmdlet?.RunScript(getCmdletsCommand) ?? RunScript(getCmdletsCommand)) .Where(ci => ci.CommandType != CommandTypes.Alias); } public static IEnumerable GetModuleCmdlets(params string[] modulePaths) => GetModuleCmdlets(null, modulePaths); public static IEnumerable GetScriptCmdlets(PSCmdlet cmdlet, string scriptFolder) { // https://stackoverflow.com/a/40969712/294804 var wrappedFolder = scriptFolder.Contains("'") ? $@"""{scriptFolder}""" : $@"'{scriptFolder}'"; var getCmdletsCommand = $@" $currentFunctions = Get-ChildItem function: Get-ChildItem -Path {wrappedFolder} -Recurse -Include '*.ps1' -File | ForEach-Object {{ . $_.FullName }} Get-ChildItem function: | Where-Object {{ ($currentFunctions -notcontains $_) -and $_.CmdletBinding }} "; return cmdlet?.RunScript(getCmdletsCommand) ?? RunScript(getCmdletsCommand); } public static IEnumerable GetScriptCmdlets(string scriptFolder) => GetScriptCmdlets(null, scriptFolder); public static IEnumerable GetScriptHelpInfo(PSCmdlet cmdlet, params string[] modulePaths) { var importModules = String.Join(Environment.NewLine, modulePaths.Select(mp => $"Import-Module '{mp}'")); var getHelpCommand = $@" $currentFunctions = Get-ChildItem function: {importModules} Get-ChildItem function: | Where-Object {{ ($currentFunctions -notcontains $_) -and $_.CmdletBinding }} | ForEach-Object {{ Get-Help -Name $_.Name -Full }} "; return cmdlet?.RunScript(getHelpCommand) ?? RunScript(getHelpCommand); } public static IEnumerable GetScriptHelpInfo(params string[] modulePaths) => GetScriptHelpInfo(null, modulePaths); public static IEnumerable GetModuleCmdletsAndHelpInfo(PSCmdlet cmdlet, params string[] modulePaths) { var getCmdletAndHelp = String.Join(" + ", modulePaths.Select(mp => $@"(Get-Command -Module (Import-Module '{mp}' -PassThru) | Where-Object {{ $_.CommandType -ne 'Alias' }} | ForEach-Object {{ @{{ CommandInfo = $_; HelpInfo = ( invoke-command {{ try {{ Get-Help -Name $_.Name -Full }} catch{{ '' }} }} ) }} }})" )); return (cmdlet?.RunScript(getCmdletAndHelp) ?? RunScript(getCmdletAndHelp)) .Select(h => new CmdletAndHelpInfo { CommandInfo = (h["CommandInfo"] as PSObject)?.BaseObject as CommandInfo, HelpInfo = h["HelpInfo"] as PSObject }); } public static IEnumerable GetModuleCmdletsAndHelpInfo(params string[] modulePaths) => GetModuleCmdletsAndHelpInfo(null, modulePaths); public static CmdletAndHelpInfo ToCmdletAndHelpInfo(this CommandInfo commandInfo, PSObject helpInfo) => new CmdletAndHelpInfo { CommandInfo = commandInfo, HelpInfo = helpInfo }; public const string Psd1Indent = " "; public const string GuidStart = Psd1Indent + "GUID"; public static Guid ReadGuidFromPsd1(string psd1Path) { var guid = Guid.NewGuid(); if (File.Exists(psd1Path)) { var currentGuid = File.ReadAllLines(psd1Path) .FirstOrDefault(l => l.TrimStart().StartsWith(GuidStart.TrimStart()))?.Split(new[] { " = " }, StringSplitOptions.RemoveEmptyEntries) .LastOrDefault()?.Replace("'", String.Empty); guid = currentGuid != null ? Guid.Parse(currentGuid) : guid; } return guid; } } internal class CmdletAndHelpInfo { public CommandInfo CommandInfo { get; set; } public PSObject HelpInfo { get; set; } } }