mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-21 14:55:06 +00:00
https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1504.md
900 lines
29 KiB
C#
900 lines
29 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Management.Automation;
|
|
using System.Management.Automation.Internal;
|
|
using System.Management.Automation.Runspaces;
|
|
|
|
namespace Microsoft.PowerShell.Commands.Internal.Format
|
|
{
|
|
/// <summary>
|
|
/// Base class defining the formatting context and the
|
|
/// formatting context manager (stack based)
|
|
/// </summary>
|
|
internal class InnerFormatShapeCommandBase : ImplementationCommandBase
|
|
{
|
|
/// <summary>
|
|
/// Constructor to set up the formatting context.
|
|
/// </summary>
|
|
internal InnerFormatShapeCommandBase()
|
|
{
|
|
contextManager.Push(FormattingContextState.none);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enum listing the possible states the context is in.
|
|
/// </summary>
|
|
internal enum FormattingContextState { none, document, group }
|
|
|
|
/// <summary>
|
|
/// Context manager: stack to keep track in which context
|
|
/// the formatter is.
|
|
/// </summary>
|
|
protected Stack<FormattingContextState> contextManager = new Stack<FormattingContextState>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Core inner implementation for format/xxx commands.
|
|
/// </summary>
|
|
internal class InnerFormatShapeCommand : InnerFormatShapeCommandBase
|
|
{
|
|
/// <summary>
|
|
/// Constructor to glue to the CRO.
|
|
/// </summary>
|
|
internal InnerFormatShapeCommand(FormatShape shape)
|
|
{
|
|
_shape = shape;
|
|
}
|
|
|
|
internal static int FormatEnumerationLimit()
|
|
{
|
|
object enumLimitVal = null;
|
|
try
|
|
{
|
|
// Win8: 192504
|
|
if (LocalPipeline.GetExecutionContextFromTLS() != null)
|
|
{
|
|
enumLimitVal = LocalPipeline.GetExecutionContextFromTLS()
|
|
.SessionState.PSVariable
|
|
.GetValue("global:" + InitialSessionState.FormatEnumerationLimit);
|
|
}
|
|
}
|
|
// Eat the following exceptions, enumerationLimit will use the default value
|
|
catch (ProviderNotFoundException)
|
|
{
|
|
}
|
|
catch (ProviderInvocationException)
|
|
{
|
|
}
|
|
|
|
// if $global:FormatEnumerationLimit is an int, overwrite the default value
|
|
return enumLimitVal is int ? (int)enumLimitVal : InitialSessionState.DefaultFormatEnumerationLimit;
|
|
}
|
|
|
|
internal override void BeginProcessing()
|
|
{
|
|
base.BeginProcessing();
|
|
|
|
// Get the Format Enumeration Limit.
|
|
_enumerationLimit = InnerFormatShapeCommand.FormatEnumerationLimit();
|
|
|
|
_expressionFactory = new PSPropertyExpressionFactory();
|
|
|
|
_formatObjectDeserializer = new FormatObjectDeserializer(this.TerminatingErrorContext);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Execution entry point.
|
|
/// </summary>
|
|
internal override void ProcessRecord()
|
|
{
|
|
_typeInfoDataBase = this.OuterCmdlet().Context.FormatDBManager.GetTypeInfoDataBase();
|
|
|
|
PSObject so = this.ReadObject();
|
|
if (so == null || so == AutomationNull.Value)
|
|
return;
|
|
|
|
IEnumerable e = PSObjectHelper.GetEnumerable(so);
|
|
if (e == null)
|
|
{
|
|
ProcessObject(so);
|
|
return;
|
|
}
|
|
|
|
// we have an IEnumerable, we have to decide if to expand, if at all
|
|
EnumerableExpansion expansionState = this.GetExpansionState(so);
|
|
|
|
switch (expansionState)
|
|
{
|
|
case EnumerableExpansion.EnumOnly:
|
|
{
|
|
foreach (object obj in e)
|
|
{
|
|
ProcessObject(PSObjectHelper.AsPSObject(obj));
|
|
}
|
|
}
|
|
|
|
break;
|
|
case EnumerableExpansion.Both:
|
|
{
|
|
var objs = e.Cast<object>().ToArray();
|
|
|
|
ProcessCoreOutOfBand(so, objs.Length);
|
|
foreach (object obj in objs)
|
|
{
|
|
ProcessObject(PSObjectHelper.AsPSObject(obj));
|
|
}
|
|
}
|
|
|
|
break;
|
|
default:
|
|
{
|
|
// do not enumerate at all (CoreOnly)
|
|
ProcessObject(so);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
private EnumerableExpansion GetExpansionState(PSObject so)
|
|
{
|
|
// if the command line swtich has been specified, use this as an override
|
|
if (_parameters != null && _parameters.expansion.HasValue)
|
|
{
|
|
return _parameters.expansion.Value;
|
|
}
|
|
|
|
// check if we have an expansion entry in format.mshxml
|
|
var typeNames = so.InternalTypeNames;
|
|
return DisplayDataQuery.GetEnumerableExpansionFromType(
|
|
_expressionFactory, _typeInfoDataBase, typeNames);
|
|
}
|
|
|
|
private void ProcessCoreOutOfBand(PSObject so, int count)
|
|
{
|
|
// emit some description header
|
|
SendCommentOutOfBand(FormatAndOut_format_xxx.IEnum_Header);
|
|
|
|
// emit the object as out of band
|
|
ProcessOutOfBand(so, isProcessingError: false);
|
|
|
|
string msg;
|
|
// emit a comment to signal that the next N objects are from the IEnumerable
|
|
switch (count)
|
|
{
|
|
case 0:
|
|
{
|
|
msg = FormatAndOut_format_xxx.IEnum_NoObjects;
|
|
}
|
|
|
|
break;
|
|
case 1:
|
|
{
|
|
msg = FormatAndOut_format_xxx.IEnum_OneObject;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
{
|
|
msg = StringUtil.Format(FormatAndOut_format_xxx.IEnum_ManyObjects, count);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
SendCommentOutOfBand(msg);
|
|
}
|
|
|
|
private void SendCommentOutOfBand(string msg)
|
|
{
|
|
FormatEntryData fed = OutOfBandFormatViewManager.GenerateOutOfBandObjectAsToString(PSObjectHelper.AsPSObject(msg));
|
|
if (fed != null)
|
|
{
|
|
this.WriteObject(fed);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Execute formatting on a single object.
|
|
/// </summary>
|
|
/// <param name="so">Object to process.</param>
|
|
private void ProcessObject(PSObject so)
|
|
{
|
|
// we do protect against reentrancy, assuming
|
|
// no fancy multiplexing
|
|
if (_formatObjectDeserializer.IsFormatInfoData(so))
|
|
{
|
|
// we are already formatted...
|
|
this.WriteObject(so);
|
|
return;
|
|
}
|
|
|
|
// if objects have to be treated as out of band, just
|
|
// bail now
|
|
// this is the case of objects coming before the
|
|
// context manager is properly set
|
|
if (ProcessOutOfBandObjectOutsideDocumentSequence(so))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// if we haven't started yet, need to do so
|
|
FormattingContextState ctx = contextManager.Peek();
|
|
if (ctx == FormattingContextState.none)
|
|
{
|
|
// initialize the view manager
|
|
_viewManager.Initialize(this.TerminatingErrorContext, _expressionFactory, _typeInfoDataBase, so, _shape, _parameters);
|
|
|
|
// add the start message to output queue
|
|
WriteFormatStartData(so);
|
|
|
|
// enter the document context
|
|
contextManager.Push(FormattingContextState.document);
|
|
}
|
|
|
|
// if we are here, we are either in the document document, or in a group
|
|
|
|
// since we have a view now, we check if objects should be treated as out of band
|
|
if (ProcessOutOfBandObjectInsideDocumentSequence(so))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// check if we have to enter or exit a group
|
|
GroupTransition transition = ComputeGroupTransition(so);
|
|
if (transition == GroupTransition.enter)
|
|
{
|
|
// insert the group start marker
|
|
PushGroup(so);
|
|
this.WritePayloadObject(so);
|
|
}
|
|
else if (transition == GroupTransition.exit)
|
|
{
|
|
this.WritePayloadObject(so);
|
|
// insert the group end marker
|
|
PopGroup();
|
|
}
|
|
else if (transition == GroupTransition.startNew)
|
|
{
|
|
// Add newline before each group except first
|
|
WriteNewLineObject();
|
|
|
|
// double transition
|
|
PopGroup(); // exit the current one
|
|
PushGroup(so); // start a sibling group
|
|
this.WritePayloadObject(so);
|
|
}
|
|
else // none, we did not have any transitions, just push out the data
|
|
{
|
|
this.WritePayloadObject(so);
|
|
}
|
|
}
|
|
|
|
private void WriteNewLineObject()
|
|
{
|
|
FormatEntryData fed = new FormatEntryData();
|
|
fed.outOfBand = true;
|
|
|
|
ComplexViewEntry cve = new ComplexViewEntry();
|
|
FormatEntry fe = new FormatEntry();
|
|
cve.formatValueList.Add(fe);
|
|
|
|
// Formating system writes newline before each object
|
|
// so no need to add newline here like:
|
|
// fe.formatValueList.Add(new FormatNewLine());
|
|
fed.formatEntryInfo = cve;
|
|
|
|
this.WriteObject(fed);
|
|
}
|
|
|
|
private bool ShouldProcessOutOfBand
|
|
{
|
|
get
|
|
{
|
|
if (_shape == FormatShape.Undefined || _parameters == null)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return !_parameters.forceFormattingAlsoOnOutOfBand;
|
|
}
|
|
}
|
|
|
|
private bool ProcessOutOfBandObjectOutsideDocumentSequence(PSObject so)
|
|
{
|
|
if (!ShouldProcessOutOfBand)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (so.InternalTypeNames.Count == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
List<ErrorRecord> errors;
|
|
var fed = OutOfBandFormatViewManager.GenerateOutOfBandData(this.TerminatingErrorContext, _expressionFactory,
|
|
_typeInfoDataBase, so, _enumerationLimit, false, out errors);
|
|
WriteErrorRecords(errors);
|
|
|
|
if (fed != null)
|
|
{
|
|
this.WriteObject(fed);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private bool ProcessOutOfBandObjectInsideDocumentSequence(PSObject so)
|
|
{
|
|
if (!ShouldProcessOutOfBand)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var typeNames = so.InternalTypeNames;
|
|
if (_viewManager.ViewGenerator.IsObjectApplicable(typeNames))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return ProcessOutOfBand(so, isProcessingError: false);
|
|
}
|
|
|
|
private bool ProcessOutOfBand(PSObject so, bool isProcessingError)
|
|
{
|
|
List<ErrorRecord> errors;
|
|
FormatEntryData fed = OutOfBandFormatViewManager.GenerateOutOfBandData(this.TerminatingErrorContext, _expressionFactory,
|
|
_typeInfoDataBase, so, _enumerationLimit, true, out errors);
|
|
if (!isProcessingError)
|
|
WriteErrorRecords(errors);
|
|
|
|
if (fed != null)
|
|
{
|
|
this.WriteObject(fed);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
protected void WriteInternalErrorMessage(string message)
|
|
{
|
|
FormatEntryData fed = new FormatEntryData();
|
|
fed.outOfBand = true;
|
|
|
|
ComplexViewEntry cve = new ComplexViewEntry();
|
|
FormatEntry fe = new FormatEntry();
|
|
cve.formatValueList.Add(fe);
|
|
|
|
fe.formatValueList.Add(new FormatNewLine());
|
|
|
|
// get a field for the message
|
|
FormatTextField ftf = new FormatTextField();
|
|
ftf.text = message;
|
|
fe.formatValueList.Add(ftf);
|
|
|
|
fe.formatValueList.Add(new FormatNewLine());
|
|
|
|
fed.formatEntryInfo = cve;
|
|
|
|
this.WriteObject(fed);
|
|
}
|
|
|
|
private void WriteErrorRecords(List<ErrorRecord> errorRecordList)
|
|
{
|
|
if (errorRecordList == null)
|
|
return;
|
|
|
|
// NOTE: for the time being we directly process error records.
|
|
// This is should change if we hook up error pipelines; for the
|
|
// time being, this achieves partial results.
|
|
//
|
|
// see NTRAID#Windows OS Bug-932722-2004/10/21-kevinloo ("Output: SS: Swallowing exceptions")
|
|
foreach (ErrorRecord errorRecord in errorRecordList)
|
|
{
|
|
// we are recursing on formatting errors: isProcessingError == true
|
|
ProcessOutOfBand(PSObjectHelper.AsPSObject(errorRecord), true);
|
|
}
|
|
}
|
|
|
|
internal override void EndProcessing()
|
|
{
|
|
// need to pop all the contexts, in case the transmission sequence
|
|
// was interrupted
|
|
while (true)
|
|
{
|
|
FormattingContextState ctx = contextManager.Peek();
|
|
|
|
if (ctx == FormattingContextState.none)
|
|
{
|
|
break; // we emerged and we are done
|
|
}
|
|
else if (ctx == FormattingContextState.group)
|
|
{
|
|
PopGroup();
|
|
}
|
|
else if (ctx == FormattingContextState.document)
|
|
{
|
|
// inject the end format information
|
|
FormatEndData endFormat = new FormatEndData();
|
|
this.WriteObject(endFormat);
|
|
contextManager.Pop();
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void SetCommandLineParameters(FormattingCommandLineParameters commandLineParameters)
|
|
{
|
|
Diagnostics.Assert(commandLineParameters != null, "the caller has to pass a valid instance");
|
|
_parameters = commandLineParameters;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Group transitions:
|
|
/// none: stay in the same group
|
|
/// enter: start a new group
|
|
/// exit: exit from the current group.
|
|
/// </summary>
|
|
private enum GroupTransition { none, enter, exit, startNew }
|
|
|
|
/// <summary>
|
|
/// Compute the group transition, given an input object.
|
|
/// </summary>
|
|
/// <param name="so">Object received from the input pipeline.</param>
|
|
/// <returns>GroupTransition enumeration.</returns>
|
|
private GroupTransition ComputeGroupTransition(PSObject so)
|
|
{
|
|
// check if we have to start a group
|
|
FormattingContextState ctx = contextManager.Peek();
|
|
if (ctx == FormattingContextState.document)
|
|
{
|
|
// prime the grouping algorithm
|
|
_viewManager.ViewGenerator.UpdateGroupingKeyValue(so);
|
|
|
|
// need to start a group, but we are not in one
|
|
return GroupTransition.enter;
|
|
}
|
|
|
|
// check if we need to start another group and keep track
|
|
// of the current value for the grouping property
|
|
return _viewManager.ViewGenerator.UpdateGroupingKeyValue(so) ? GroupTransition.startNew : GroupTransition.none;
|
|
}
|
|
|
|
private void WriteFormatStartData(PSObject so)
|
|
{
|
|
FormatStartData startFormat = _viewManager.ViewGenerator.GenerateStartData(so);
|
|
this.WriteObject(startFormat);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write a payplad object by properly wrapping it into
|
|
/// a FormatEntry object.
|
|
/// </summary>
|
|
/// <param name="so">Object to process.</param>
|
|
private void WritePayloadObject(PSObject so)
|
|
{
|
|
Diagnostics.Assert(so != null, "object so cannot be null");
|
|
FormatEntryData fed = _viewManager.ViewGenerator.GeneratePayload(so, _enumerationLimit);
|
|
fed.writeStream = so.WriteStream;
|
|
this.WriteObject(fed);
|
|
|
|
List<ErrorRecord> errors = _viewManager.ViewGenerator.ErrorManager.DrainFailedResultList();
|
|
WriteErrorRecords(errors);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inject the start group information
|
|
/// and push group context on stack.
|
|
/// </summary>
|
|
/// <param name="firstObjectInGroup">current pipeline object
|
|
/// that is starting the group</param>
|
|
private void PushGroup(PSObject firstObjectInGroup)
|
|
{
|
|
GroupStartData startGroup = _viewManager.ViewGenerator.GenerateGroupStartData(firstObjectInGroup, _enumerationLimit);
|
|
this.WriteObject(startGroup);
|
|
contextManager.Push(FormattingContextState.group);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inject the end group information
|
|
/// and pop group context out of stack.
|
|
/// </summary>
|
|
private void PopGroup()
|
|
{
|
|
GroupEndData endGroup = _viewManager.ViewGenerator.GenerateGroupEndData();
|
|
this.WriteObject(endGroup);
|
|
contextManager.Pop();
|
|
}
|
|
|
|
/// <summary>
|
|
/// The formatting shape this formatter emits.
|
|
/// </summary>
|
|
private readonly FormatShape _shape;
|
|
|
|
#region expression factory
|
|
|
|
/// <exception cref="ParseException"></exception>
|
|
internal ScriptBlock CreateScriptBlock(string scriptText)
|
|
{
|
|
var scriptBlock = this.OuterCmdlet().InvokeCommand.NewScriptBlock(scriptText);
|
|
scriptBlock.DebuggerStepThrough = true;
|
|
return scriptBlock;
|
|
}
|
|
|
|
private PSPropertyExpressionFactory _expressionFactory;
|
|
#endregion
|
|
|
|
private FormatObjectDeserializer _formatObjectDeserializer;
|
|
|
|
private TypeInfoDataBase _typeInfoDataBase = null;
|
|
|
|
private FormattingCommandLineParameters _parameters = null;
|
|
private readonly FormatViewManager _viewManager = new FormatViewManager();
|
|
|
|
private int _enumerationLimit = InitialSessionState.DefaultFormatEnumerationLimit;
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
public class OuterFormatShapeCommandBase : FrontEndCommandBase
|
|
{
|
|
#region Command Line Switches
|
|
|
|
/// <summary>
|
|
/// Optional, non positional parameter to specify the
|
|
/// group by property.
|
|
/// </summary>
|
|
[Parameter]
|
|
public object GroupBy { get; set; } = null;
|
|
|
|
/// <summary>
|
|
/// Optional, non positional parameter.
|
|
/// </summary>
|
|
/// <value></value>
|
|
[Parameter]
|
|
public string View { get; set; } = null;
|
|
|
|
/// <summary>
|
|
/// Optional, non positional parameter.
|
|
/// </summary>
|
|
/// <value></value>
|
|
[Parameter]
|
|
public SwitchParameter ShowError
|
|
{
|
|
get
|
|
{
|
|
if (showErrorsAsMessages.HasValue)
|
|
return showErrorsAsMessages.Value;
|
|
return false;
|
|
}
|
|
|
|
set
|
|
{
|
|
showErrorsAsMessages = value;
|
|
}
|
|
}
|
|
|
|
internal bool? showErrorsAsMessages = null;
|
|
|
|
/// <summary>
|
|
/// Optional, non positional parameter.
|
|
/// </summary>
|
|
/// <value></value>
|
|
[Parameter]
|
|
public SwitchParameter DisplayError
|
|
{
|
|
get
|
|
{
|
|
if (showErrorsInFormattedOutput.HasValue)
|
|
return showErrorsInFormattedOutput.Value;
|
|
return false;
|
|
}
|
|
|
|
set
|
|
{
|
|
showErrorsInFormattedOutput = value;
|
|
}
|
|
}
|
|
|
|
internal bool? showErrorsInFormattedOutput = null;
|
|
|
|
/// <summary>
|
|
/// Optional, non positional parameter.
|
|
/// </summary>
|
|
/// <value></value>
|
|
[Parameter]
|
|
public SwitchParameter Force
|
|
{
|
|
get { return _forceFormattingAlsoOnOutOfBand; }
|
|
|
|
set { _forceFormattingAlsoOnOutOfBand = value; }
|
|
}
|
|
|
|
private bool _forceFormattingAlsoOnOutOfBand;
|
|
|
|
/// <summary>
|
|
/// Optional, non positional parameter.
|
|
/// </summary>
|
|
/// <value></value>
|
|
[Parameter]
|
|
[ValidateSet(EnumerableExpansionConversion.CoreOnlyString,
|
|
EnumerableExpansionConversion.EnumOnlyString,
|
|
EnumerableExpansionConversion.BothString, IgnoreCase = true)]
|
|
public string Expand { get; set; } = null;
|
|
|
|
internal EnumerableExpansion? expansion = null;
|
|
|
|
internal EnumerableExpansion? ProcessExpandParameter()
|
|
{
|
|
EnumerableExpansion? retVal = null;
|
|
if (string.IsNullOrEmpty(Expand))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
EnumerableExpansion temp;
|
|
bool success = EnumerableExpansionConversion.Convert(Expand, out temp);
|
|
if (!success)
|
|
{
|
|
// this should never happen, since we use the [ValidateSet] attribute
|
|
// NOTE: this is an exception that should never be triggered
|
|
throw PSTraceSource.NewArgumentException("Expand", FormatAndOut_MshParameter.IllegalEnumerableExpansionValue);
|
|
}
|
|
|
|
retVal = temp;
|
|
return retVal;
|
|
}
|
|
|
|
internal MshParameter ProcessGroupByParameter()
|
|
{
|
|
if (GroupBy != null)
|
|
{
|
|
TerminatingErrorContext invocationContext =
|
|
new TerminatingErrorContext(this);
|
|
ParameterProcessor processor = new ParameterProcessor(new FormatGroupByParameterDefinition());
|
|
List<MshParameter> groupParameterList =
|
|
processor.ProcessParameters(new object[] { GroupBy },
|
|
invocationContext);
|
|
|
|
if (groupParameterList.Count != 0)
|
|
return groupParameterList[0];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
protected override void BeginProcessing()
|
|
{
|
|
InnerFormatShapeCommand innerFormatCommand =
|
|
(InnerFormatShapeCommand)this.implementation;
|
|
|
|
// read command line switches and pass them to the inner command
|
|
FormattingCommandLineParameters parameters = GetCommandLineParameters();
|
|
innerFormatCommand.SetCommandLineParameters(parameters);
|
|
|
|
// must call base class for further processing
|
|
base.BeginProcessing();
|
|
}
|
|
|
|
/// <summary>
|
|
/// It reads the command line switches and collects them into a
|
|
/// FormattingCommandLineParameters instance, ready to pass to the
|
|
/// inner format command.
|
|
/// </summary>
|
|
/// <returns>Parameters collected in unified manner.</returns>
|
|
internal virtual FormattingCommandLineParameters GetCommandLineParameters()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
internal void ReportCannotSpecifyViewAndProperty()
|
|
{
|
|
string msg = StringUtil.Format(FormatAndOut_format_xxx.CannotSpecifyViewAndPropertyError);
|
|
|
|
ErrorRecord errorRecord = new ErrorRecord(
|
|
new InvalidDataException(),
|
|
"FormatCannotSpecifyViewAndProperty",
|
|
ErrorCategory.InvalidArgument,
|
|
null);
|
|
|
|
errorRecord.ErrorDetails = new ErrorDetails(msg);
|
|
this.ThrowTerminatingError(errorRecord);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
public class OuterFormatTableAndListBase : OuterFormatShapeCommandBase
|
|
{
|
|
#region Command Line Switches
|
|
|
|
/// <summary>
|
|
/// Positional parameter for properties, property sets and table sets
|
|
/// specified on the command line.
|
|
/// The parameter is optional, since the defaults
|
|
/// will be determined using property sets, etc.
|
|
/// </summary>
|
|
[Parameter(Position = 0)]
|
|
public object[] Property { get; set; }
|
|
|
|
#endregion
|
|
|
|
internal override FormattingCommandLineParameters GetCommandLineParameters()
|
|
{
|
|
FormattingCommandLineParameters parameters = new FormattingCommandLineParameters();
|
|
|
|
GetCommandLineProperties(parameters, false);
|
|
parameters.groupByParameter = this.ProcessGroupByParameter();
|
|
|
|
parameters.forceFormattingAlsoOnOutOfBand = this.Force;
|
|
if (this.showErrorsAsMessages.HasValue)
|
|
parameters.showErrorsAsMessages = this.showErrorsAsMessages;
|
|
if (this.showErrorsInFormattedOutput.HasValue)
|
|
parameters.showErrorsInFormattedOutput = this.showErrorsInFormattedOutput;
|
|
|
|
parameters.expansion = ProcessExpandParameter();
|
|
|
|
return parameters;
|
|
}
|
|
|
|
internal void GetCommandLineProperties(FormattingCommandLineParameters parameters, bool isTable)
|
|
{
|
|
if (Property != null)
|
|
{
|
|
CommandParameterDefinition def;
|
|
|
|
if (isTable)
|
|
def = new FormatTableParameterDefinition();
|
|
else
|
|
def = new FormatListParameterDefinition();
|
|
ParameterProcessor processor = new ParameterProcessor(def);
|
|
TerminatingErrorContext invocationContext = new TerminatingErrorContext(this);
|
|
|
|
parameters.mshParameterList = processor.ProcessParameters(Property, invocationContext);
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(this.View))
|
|
{
|
|
// we have a view command line switch
|
|
if (parameters.mshParameterList.Count != 0)
|
|
{
|
|
ReportCannotSpecifyViewAndProperty();
|
|
}
|
|
|
|
parameters.viewName = this.View;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
public class OuterFormatTableBase : OuterFormatTableAndListBase
|
|
{
|
|
#region Command Line Switches
|
|
|
|
/// <summary>
|
|
/// Optional, non positional parameter.
|
|
/// </summary>
|
|
/// <value></value>
|
|
[Parameter]
|
|
public SwitchParameter AutoSize
|
|
{
|
|
get
|
|
{
|
|
if (_autosize.HasValue)
|
|
return _autosize.Value;
|
|
return false;
|
|
}
|
|
|
|
set
|
|
{
|
|
_autosize = value;
|
|
}
|
|
}
|
|
|
|
private bool? _autosize = null;
|
|
|
|
/// <summary>
|
|
/// Gets or sets if header is repeated per screen.
|
|
/// </summary>
|
|
[Parameter]
|
|
public SwitchParameter RepeatHeader { get; set; }
|
|
|
|
/// <summary>
|
|
/// Optional, non positional parameter.
|
|
/// </summary>
|
|
/// <value></value>
|
|
[Parameter]
|
|
public SwitchParameter HideTableHeaders
|
|
{
|
|
get
|
|
{
|
|
if (_hideHeaders.HasValue)
|
|
return _hideHeaders.Value;
|
|
return false;
|
|
}
|
|
|
|
set
|
|
{
|
|
_hideHeaders = value;
|
|
}
|
|
}
|
|
|
|
private bool? _hideHeaders = null;
|
|
|
|
/// <summary>
|
|
/// Optional, non positional parameter.
|
|
/// </summary>
|
|
/// <value></value>
|
|
[Parameter]
|
|
public SwitchParameter Wrap
|
|
{
|
|
get
|
|
{
|
|
if (_multiLine.HasValue)
|
|
return _multiLine.Value;
|
|
return false;
|
|
}
|
|
|
|
set
|
|
{
|
|
_multiLine = value;
|
|
}
|
|
}
|
|
|
|
private bool? _multiLine = null;
|
|
|
|
#endregion
|
|
internal override FormattingCommandLineParameters GetCommandLineParameters()
|
|
{
|
|
FormattingCommandLineParameters parameters = new FormattingCommandLineParameters();
|
|
|
|
GetCommandLineProperties(parameters, true);
|
|
parameters.forceFormattingAlsoOnOutOfBand = this.Force;
|
|
if (this.showErrorsAsMessages.HasValue)
|
|
parameters.showErrorsAsMessages = this.showErrorsAsMessages;
|
|
if (this.showErrorsInFormattedOutput.HasValue)
|
|
parameters.showErrorsInFormattedOutput = this.showErrorsInFormattedOutput;
|
|
|
|
parameters.expansion = ProcessExpandParameter();
|
|
|
|
if (_autosize.HasValue)
|
|
parameters.autosize = _autosize.Value;
|
|
|
|
if (RepeatHeader)
|
|
{
|
|
parameters.repeatHeader = true;
|
|
}
|
|
|
|
parameters.groupByParameter = this.ProcessGroupByParameter();
|
|
|
|
TableSpecificParameters tableParameters = new TableSpecificParameters();
|
|
parameters.shapeParameters = tableParameters;
|
|
|
|
if (_hideHeaders.HasValue)
|
|
{
|
|
tableParameters.hideHeaders = _hideHeaders.Value;
|
|
}
|
|
|
|
if (_multiLine.HasValue)
|
|
{
|
|
tableParameters.multiLine = _multiLine.Value;
|
|
}
|
|
|
|
return parameters;
|
|
}
|
|
}
|
|
}
|