Adding verbose output for experimental implicit remoting batching feature (#8166)

This commit is contained in:
Paul Higinbotham 2018-11-05 15:22:46 -08:00 committed by Aditya Patwardhan
parent e1d8765f9e
commit acf5eb5053
2 changed files with 72 additions and 28 deletions

View file

@ -1382,38 +1382,40 @@ namespace System.Management.Automation
// c. Commands must be in a simple pipeline
internal static bool TryRunAsImplicitBatch(string command, Runspace runspace)
{
try
using (var ps = System.Management.Automation.PowerShell.Create())
{
var scriptBlock = ScriptBlock.Create(command);
var scriptBlockAst = scriptBlock.Ast as ScriptBlockAst;
if (scriptBlockAst == null)
{
return false;
}
ps.Runspace = runspace;
// Make sure that this is a simple pipeline
string errorId;
string errorMsg;
scriptBlockAst.GetSimplePipeline(true, out errorId, out errorMsg);
if (errorId != null)
try
{
return false;
}
var scriptBlock = ScriptBlock.Create(command);
var scriptBlockAst = scriptBlock.Ast as ScriptBlockAst;
if (scriptBlockAst == null)
{
return false;
}
// Run checker
var checker = new PipelineForBatchingChecker { ScriptBeingConverted = scriptBlockAst };
scriptBlockAst.InternalVisit(checker);
// Make sure that this is a simple pipeline
string errorId;
string errorMsg;
scriptBlockAst.GetSimplePipeline(true, out errorId, out errorMsg);
if (errorId != null)
{
WriteVerbose(ps, ParserStrings.ImplicitRemotingPipelineBatchingNotASimplePipeline);
return false;
}
// If this is just a single command, there is no point in batching it
if (checker.Commands.Count < 2)
{
return false;
}
// Run checker
var checker = new PipelineForBatchingChecker { ScriptBeingConverted = scriptBlockAst };
scriptBlockAst.InternalVisit(checker);
// We have a valid batching candidate
using (var ps = System.Management.Automation.PowerShell.Create())
{
ps.Runspace = runspace;
// If this is just a single command, there is no point in batching it
if (checker.Commands.Count < 2)
{
return false;
}
// We have a valid batching candidate
// Check commands
if (!TryGetCommandInfoList(ps, checker.Commands, out Collection<CommandInfo> cmdInfoList))
@ -1436,6 +1438,7 @@ namespace System.Management.Automation
// Commands must be from implicit remoting module
if (cmdInfo.Module == null || string.IsNullOrEmpty(cmdInfo.ModuleName))
{
WriteVerbose(ps, string.Format(CultureInfo.CurrentCulture, ParserStrings.ImplicitRemotingPipelineBatchingNotImplicitCommand, cmdInfo.Name));
success = false;
break;
}
@ -1446,6 +1449,7 @@ namespace System.Management.Automation
var sessionIdString = privateData["ImplicitSessionId"] as string;
if (string.IsNullOrEmpty(sessionIdString))
{
WriteVerbose(ps, string.Format(CultureInfo.CurrentCulture, ParserStrings.ImplicitRemotingPipelineBatchingNotImplicitCommand, cmdInfo.Name));
success = false;
break;
}
@ -1457,12 +1461,14 @@ namespace System.Management.Automation
}
else if (psSessionId != sessionId)
{
WriteVerbose(ps, string.Format(CultureInfo.CurrentCulture, ParserStrings.ImplicitRemotingPipelineBatchingWrongSession, cmdInfo.Name));
success = false;
break;
}
}
else
{
WriteVerbose(ps, string.Format(CultureInfo.CurrentCulture, ParserStrings.ImplicitRemotingPipelineBatchingNotImplicitCommand, cmdInfo.Name));
success = false;
break;
}
@ -1491,13 +1497,20 @@ namespace System.Management.Automation
var psSession = ps.Invoke<System.Management.Automation.Runspaces.PSSession>().FirstOrDefault();
if (psSession == null || (ps.Streams.Error.Count > 0) || (psSession.Availability != RunspaceAvailability.Available))
{
WriteVerbose(ps, ParserStrings.ImplicitRemotingPipelineBatchingNoPSSession);
return false;
}
WriteVerbose(ps, ParserStrings.ImplicitRemotingPipelineBatchingSuccess);
// Create and invoke implicit remoting command pipeline
ps.Commands.Clear();
ps.AddCommand("Invoke-Command").AddParameter("Session", psSession).AddParameter("ScriptBlock", scriptBlock).AddParameter("HideComputerName", true)
.AddCommand("Out-Default");
foreach (var cmd in ps.Commands.Commands)
{
cmd.MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
}
try
{
@ -1514,12 +1527,25 @@ namespace System.Management.Automation
return true;
}
}
catch (ImplicitRemotingBatchingNotSupportedException ex)
{
WriteVerbose(ps, string.Format(CultureInfo.CurrentCulture, "{0} : {1}", ex.Message, ex.ErrorId));
}
catch (Exception ex)
{
WriteVerbose(ps, string.Format(CultureInfo.CurrentCulture, ParserStrings.ImplicitRemotingPipelineBatchingException, ex.Message));
}
}
catch (Exception) { }
return false;
}
private static void WriteVerbose(PowerShell ps, string msg)
{
ps.Commands.Clear();
ps.AddCommand("Write-Verbose").AddParameter("Message", msg).Invoke();
}
private const string WhereObjectCommandAlias = "?";
private static bool TryGetCommandInfoList(PowerShell ps, HashSet<string> commandNames, out Collection<CommandInfo> cmdInfoList)
{

View file

@ -1470,4 +1470,22 @@ ModuleVersion : Version of module to import. If used, ModuleName must represent
<data name="ImplicitRemotingPipelineBatchingNotSupported" xml:space="preserve">
<value>Command pipeline not supported for implicit remoting batching.</value>
</data>
<data name="ImplicitRemotingPipelineBatchingNotASimplePipeline" xml:space="preserve">
<value>Command is not a simple pipeline and cannot be batched.</value>
</data>
<data name="ImplicitRemotingPipelineBatchingNotImplicitCommand" xml:space="preserve">
<value>The pipeline command '{0}' is not an implicit remoting command or an approved batching command.</value>
</data>
<data name="ImplicitRemotingPipelineBatchingWrongSession" xml:space="preserve">
<value>The pipeline command '{0}' is for a different remote session and cannot be batched.</value>
</data>
<data name="ImplicitRemotingPipelineBatchingNoPSSession" xml:space="preserve">
<value>The implicit remoting PSSession for batching could not be retrieved.</value>
</data>
<data name="ImplicitRemotingPipelineBatchingException" xml:space="preserve">
<value>Exception while checking the command for implicit remoting batching: {0}</value>
</data>
<data name="ImplicitRemotingPipelineBatchingSuccess" xml:space="preserve">
<value>Implicit remoting command pipeline has been batched for execution on remote target.</value>
</data>
</root>