mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 20:56:02 +00:00
247 lines
9.2 KiB
C#
247 lines
9.2 KiB
C#
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq;
|
|
using System.Management.Automation;
|
|
using System.Management.Automation.Runspaces;
|
|
|
|
using Microsoft.PowerShell.Commands.Internal.Format;
|
|
|
|
namespace Microsoft.PowerShell.Commands
|
|
{
|
|
/// <summary>
|
|
/// Gets formatting information from the loading format information database.
|
|
/// </summary>
|
|
/// <remarks>Currently supports only table controls
|
|
/// </remarks>
|
|
[Cmdlet(VerbsCommon.Get, "FormatData", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=144303")]
|
|
[OutputType(typeof(System.Management.Automation.ExtendedTypeDefinition))]
|
|
public class GetFormatDataCommand : PSCmdlet
|
|
{
|
|
private string[] _typename;
|
|
private WildcardPattern[] _filter = new WildcardPattern[1];
|
|
|
|
/// <summary>
|
|
/// Get Formatting information only for the specified typename.
|
|
/// </summary>
|
|
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
|
|
[ValidateNotNullOrEmpty]
|
|
[Parameter(Position = 0)]
|
|
public string[] TypeName
|
|
{
|
|
get
|
|
{
|
|
return _typename;
|
|
}
|
|
|
|
set
|
|
{
|
|
_typename = value;
|
|
|
|
if (_typename == null)
|
|
{
|
|
_filter = Array.Empty<WildcardPattern>();
|
|
}
|
|
else
|
|
{
|
|
_filter = new WildcardPattern[_typename.Length];
|
|
for (int i = 0; i < _filter.Length; i++)
|
|
{
|
|
_filter[i] = WildcardPattern.Get(_typename[i],
|
|
WildcardOptions.Compiled | WildcardOptions.CultureInvariant | WildcardOptions.IgnoreCase);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// When specified, helps control whether or not to send richer formatting data
|
|
/// that was not supported by earlier versions of PowerShell.
|
|
/// </summary>
|
|
[Parameter]
|
|
public Version PowerShellVersion { get; set; }
|
|
|
|
/// <summary>
|
|
/// Set the default filter.
|
|
/// </summary>
|
|
protected override void BeginProcessing()
|
|
{
|
|
if (_filter[0] == null)
|
|
{
|
|
_filter[0] = WildcardPattern.Get("*", WildcardOptions.None);
|
|
}
|
|
}
|
|
|
|
private static Dictionary<string, List<string>> GetTypeGroupMap(IEnumerable<TypeGroupDefinition> groupDefinitions)
|
|
{
|
|
var typeGroupMap = new Dictionary<string, List<string>>();
|
|
foreach (TypeGroupDefinition typeGroup in groupDefinitions)
|
|
{
|
|
// The format system actually allows you to define multiple SelectionSets with the same name, but only the
|
|
// first type group will take effect. So we skip the rest groups that have the same name.
|
|
if (!typeGroupMap.ContainsKey(typeGroup.name))
|
|
{
|
|
var typesInGroup = typeGroup.typeReferenceList.Select(typeReference => typeReference.name).ToList();
|
|
typeGroupMap.Add(typeGroup.name, typesInGroup);
|
|
}
|
|
}
|
|
|
|
return typeGroupMap;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Takes out the content from the database and writes them out.
|
|
/// </summary>
|
|
protected override void ProcessRecord()
|
|
{
|
|
bool writeOldWay = PowerShellVersion == null ||
|
|
PowerShellVersion.Major < 5 ||
|
|
(PowerShellVersion.Major == 5 && PowerShellVersion.Minor < 1);
|
|
|
|
TypeInfoDataBase db = this.Context.FormatDBManager.Database;
|
|
|
|
List<ViewDefinition> viewdefinitions = db.viewDefinitionsSection.viewDefinitionList;
|
|
Dictionary<string, List<string>> typeGroupMap = GetTypeGroupMap(db.typeGroupSection.typeGroupDefinitionList);
|
|
|
|
var typedefs = new Dictionary<ConsolidatedString, List<FormatViewDefinition>>(ConsolidatedString.EqualityComparer);
|
|
|
|
foreach (ViewDefinition definition in viewdefinitions)
|
|
{
|
|
if (definition.isHelpFormatter)
|
|
continue;
|
|
|
|
var consolidatedTypeName = CreateConsolidatedTypeName(definition, typeGroupMap);
|
|
|
|
if (!ShouldGenerateView(consolidatedTypeName))
|
|
continue;
|
|
|
|
PSControl control;
|
|
|
|
var tableControlBody = definition.mainControl as TableControlBody;
|
|
if (tableControlBody != null)
|
|
{
|
|
control = new TableControl(tableControlBody, definition);
|
|
}
|
|
else
|
|
{
|
|
var listControlBody = definition.mainControl as ListControlBody;
|
|
if (listControlBody != null)
|
|
{
|
|
control = new ListControl(listControlBody, definition);
|
|
}
|
|
else
|
|
{
|
|
var wideControlBody = definition.mainControl as WideControlBody;
|
|
if (wideControlBody != null)
|
|
{
|
|
control = new WideControl(wideControlBody, definition);
|
|
if (writeOldWay)
|
|
{
|
|
// Alignment was added to WideControl in V2, but wasn't
|
|
// used. It was removed in V5, but old PowerShell clients
|
|
// expect this property or fail to rehydrate the remote object.
|
|
var psobj = new PSObject(control);
|
|
psobj.Properties.Add(new PSNoteProperty("Alignment", 0));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var complexControlBody = (ComplexControlBody)definition.mainControl;
|
|
control = new CustomControl(complexControlBody, definition);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Older version of PowerShell do not know about something in the control, so
|
|
// don't return it.
|
|
if (writeOldWay && !control.CompatibleWithOldPowerShell())
|
|
continue;
|
|
|
|
var formatdef = new FormatViewDefinition(definition.name, control, definition.InstanceId);
|
|
|
|
List<FormatViewDefinition> viewList;
|
|
if (!typedefs.TryGetValue(consolidatedTypeName, out viewList))
|
|
{
|
|
viewList = new List<FormatViewDefinition>();
|
|
typedefs.Add(consolidatedTypeName, viewList);
|
|
}
|
|
|
|
viewList.Add(formatdef);
|
|
}
|
|
|
|
// write out all the available type definitions
|
|
foreach (var pair in typedefs)
|
|
{
|
|
var typeNames = pair.Key;
|
|
|
|
if (writeOldWay)
|
|
{
|
|
foreach (var typeName in typeNames)
|
|
{
|
|
var etd = new ExtendedTypeDefinition(typeName, pair.Value);
|
|
WriteObject(etd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var etd = new ExtendedTypeDefinition(typeNames[0], pair.Value);
|
|
for (int i = 1; i < typeNames.Count; i++)
|
|
{
|
|
etd.TypeNames.Add(typeNames[i]);
|
|
}
|
|
|
|
WriteObject(etd);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static ConsolidatedString CreateConsolidatedTypeName(ViewDefinition definition, Dictionary<string, List<string>> typeGroupMap)
|
|
{
|
|
// Create our "consolidated string" typename which is used as a dictionary key
|
|
var reflist = definition.appliesTo.referenceList;
|
|
var consolidatedTypeName = new ConsolidatedString(ConsolidatedString.Empty);
|
|
|
|
foreach (TypeOrGroupReference item in reflist)
|
|
{
|
|
// If it's a TypeGroup, we need to look that up and add it's members
|
|
if (item is TypeGroupReference)
|
|
{
|
|
List<string> typesInGroup;
|
|
if (typeGroupMap.TryGetValue(item.name, out typesInGroup))
|
|
{
|
|
foreach (string typeName in typesInGroup)
|
|
{
|
|
consolidatedTypeName.Add(typeName);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
consolidatedTypeName.Add(item.name);
|
|
}
|
|
}
|
|
|
|
return consolidatedTypeName;
|
|
}
|
|
|
|
private bool ShouldGenerateView(ConsolidatedString consolidatedTypeName)
|
|
{
|
|
foreach (WildcardPattern pattern in _filter)
|
|
{
|
|
foreach (var typeName in consolidatedTypeName)
|
|
{
|
|
if (pattern.IsMatch(typeName))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|