mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
In local invocations do not require -PowerShellVersion 5.1 for Get-FormatData in order to see all format data. (#11270)
This commit is contained in:
+23
-3
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Remoting;
|
||||
using System.Management.Automation.Runspaces;
|
||||
|
||||
using Microsoft.PowerShell.Commands.Internal.Format;
|
||||
@@ -97,9 +98,28 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
bool writeOldWay = PowerShellVersion == null ||
|
||||
PowerShellVersion.Major < 5 ||
|
||||
(PowerShellVersion.Major == 5 && PowerShellVersion.Minor < 1);
|
||||
// Remoting detection:
|
||||
// * Automatic variable $PSSenderInfo is defined in true remoting contexts as well as in background jobs.
|
||||
// * $PSSenderInfo.ApplicationArguments.PSVersionTable.PSVersion contains the client version, as a [version] instance.
|
||||
// Note: Even though $PSVersionTable.PSVersion is of type [semver] in PowerShell 6+, it is of type [version] here,
|
||||
// presumably because only the latter type deserializes type-faithfully.
|
||||
var clientVersion = PowerShellVersion;
|
||||
PSSenderInfo remotingClientInfo = GetVariableValue("PSSenderInfo") as PSSenderInfo;
|
||||
if (clientVersion == null && remotingClientInfo != null)
|
||||
{
|
||||
clientVersion = PSObject.Base((PSObject.Base(remotingClientInfo.ApplicationArguments["PSVersionTable"]) as PSPrimitiveDictionary)?["PSVersion"]) as Version;
|
||||
}
|
||||
|
||||
// During remoting, remain compatible with v5.0- clients by default.
|
||||
// Passing a -PowerShellVersion argument allows overriding the client version.
|
||||
bool writeOldWay =
|
||||
(remotingClientInfo != null && clientVersion == null) // To be safe: Remoting client version could unexpectedly not be determined.
|
||||
||
|
||||
(clientVersion != null
|
||||
&&
|
||||
(clientVersion.Major < 5
|
||||
||
|
||||
(clientVersion.Major == 5 && clientVersion.Minor < 1)));
|
||||
|
||||
TypeInfoDataBase db = this.Context.FormatDBManager.Database;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ using System.Linq;
|
||||
using System.Management.Automation.Configuration;
|
||||
using System.Management.Automation.Internal;
|
||||
using System.Management.Automation.Language;
|
||||
using System.Management.Automation.Remoting;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Management.Automation.Security;
|
||||
using System.Numerics;
|
||||
@@ -2098,6 +2099,25 @@ namespace System.Management.Automation.Internal
|
||||
{
|
||||
return Utils.TryRunAsImplicitBatch(commandPipeline, runspace);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a custom PSSenderInfo instance that can be assigned to $PSSenderInfo
|
||||
/// in order to simulate a remoting session with respect to the $PSSenderInfo.ConnectionString (connection URL)
|
||||
/// and $PSSenderInfo.ApplicationArguments.PSVersionTable.PSVersion (the remoting client's PowerShell version).
|
||||
/// See Get-FormatDataTest.ps1.
|
||||
/// </summary>
|
||||
/// <param name="url">The connection URL to reflect in the returned instance's ConnectionString property.</param>
|
||||
/// <param name="clientVersion">The version number to report as the remoting client's PowerShell version.</param>
|
||||
/// <returns>The newly constructed custom PSSenderInfo instance.</returns>
|
||||
public static PSSenderInfo GetCustomPSSenderInfo(string url, Version clientVersion)
|
||||
{
|
||||
var dummyPrincipal = new PSPrincipal(new PSIdentity("none", true, "someuser", null), null);
|
||||
var pssi = new PSSenderInfo(dummyPrincipal, url);
|
||||
pssi.ApplicationArguments = new PSPrimitiveDictionary();
|
||||
pssi.ApplicationArguments.Add("PSVersionTable", new PSObject(new PSPrimitiveDictionary()));
|
||||
((PSPrimitiveDictionary)PSObject.Base(pssi.ApplicationArguments["PSVersionTable"])).Add("PSVersion", new PSObject(clientVersion));
|
||||
return pssi;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# Licensed under the MIT License.
|
||||
Describe "Export-FormatData" -Tags "CI" {
|
||||
BeforeAll {
|
||||
$fd = Get-FormatData
|
||||
$clientVersion = '5.0' # Preliminarily preserve the original test semantics in place before https://github.com/PowerShell/PowerShell/pull/11270
|
||||
$fd = Get-FormatData -PowerShellVersion $clientVersion
|
||||
$testOutput = Join-Path -Path $TestDrive -ChildPath "outputfile"
|
||||
}
|
||||
|
||||
@@ -23,7 +24,7 @@ Describe "Export-FormatData" -Tags "CI" {
|
||||
$runspace.Open()
|
||||
|
||||
$runspace.CreatePipeline("Update-FormatData -AppendPath $TESTDRIVE\allformat.ps1xml").Invoke()
|
||||
$actualAllFormat = $runspace.CreatePipeline("Get-FormatData -TypeName *").Invoke()
|
||||
$actualAllFormat = $runspace.CreatePipeline("Get-FormatData -PowerShellVersion $clientVersion").Invoke()
|
||||
|
||||
$fd.Count | Should -Be $actualAllFormat.Count
|
||||
Compare-Object $fd $actualAllFormat | Should -Be $null
|
||||
|
||||
@@ -3,24 +3,64 @@
|
||||
Describe "Get-FormatData" -Tags "CI" {
|
||||
|
||||
Context "Check return type of Get-FormatData" {
|
||||
|
||||
It "Should return an object[] as the return type" {
|
||||
$result = Get-FormatData
|
||||
,$result | Should -BeOfType System.Object[]
|
||||
, $result | Should -BeOfType "System.Object[]"
|
||||
}
|
||||
}
|
||||
|
||||
It "Can get format data requiring '-PowerShellVersion 5.1'" {
|
||||
$format = Get-FormatData System.IO.FileInfo -PowerShellVersion 5.1
|
||||
$format.TypeNames | Should -HaveCount 2
|
||||
$format.TypeNames[0] | Should -BeExactly "System.IO.DirectoryInfo"
|
||||
$format.TypeNames[1] | Should -BeExactly "System.IO.FileInfo"
|
||||
# Note: Format data for [System.IO.FileInfo] (among others) is not to be
|
||||
# returned to v5.0- remoting clients.
|
||||
|
||||
$isUnixStatEnabled = $EnabledExperimentalFeatures -contains 'PSUnixFileStat'
|
||||
$format.FormatViewDefinition | Should -HaveCount ( $isUnixStatEnabled ? 5 : 4)
|
||||
Context "Local use: Can get format data requiring v5.1+ by default" {
|
||||
BeforeAll {
|
||||
$cmds = @(
|
||||
@{ cmd = { Get-FormatData System.IO.FileInfo } }
|
||||
@{ cmd = { (Get-FormatData System.IO.FileInfo &) | Receive-Job -Wait -AutoRemoveJob } }
|
||||
)
|
||||
}
|
||||
It "Can get format data requiring v5.1+ with <cmd>" -TestCases $cmds {
|
||||
param([scriptblock] $cmd)
|
||||
$format = & $cmd
|
||||
$format.TypeNames | Should -HaveCount 2
|
||||
$format.TypeNames[0] | Should -BeExactly "System.IO.DirectoryInfo"
|
||||
$format.TypeNames[1] | Should -BeExactly "System.IO.FileInfo"
|
||||
|
||||
$isUnixStatEnabled = $EnabledExperimentalFeatures -contains 'PSUnixFileStat'
|
||||
$format.FormatViewDefinition | Should -HaveCount ($isUnixStatEnabled ? 5 : 4)
|
||||
}
|
||||
}
|
||||
|
||||
It "Should return nothing for format data requiring '-PowerShellVersion 5.1' and not provided" {
|
||||
Get-FormatData System.IO.FileInfo | Should -BeNullOrEmpty
|
||||
Context "Can override client version with -PowerShellVersion" {
|
||||
BeforeAll {
|
||||
$cmds = @(
|
||||
@{ shouldBeNull = $true; cmd = { Get-FormatData System.IO.FileInfo -PowerShellVersion 5.0 } }
|
||||
@{ shouldBeNull = $false; cmd = { Get-FormatData System.IO.FileInfo -PowerShellVersion 5.1 } }
|
||||
@{ shouldBeNull = $false; cmd = { $PSSenderInfo = [System.Management.Automation.Internal.InternalTestHooks]::GetCustomPSSenderInfo('foo', [version] '5.0'); Get-FormatData System.IO.FileInfo -PowerShellVersion 5.1 } }
|
||||
)
|
||||
}
|
||||
It "<cmd> should return <shouldBeNull> for a null-output test" -TestCases $cmds {
|
||||
param([scriptblock] $cmd, [bool] $shouldBeNull)
|
||||
$null -eq $(& $cmd) | Should -Be $shouldBeNull
|
||||
}
|
||||
}
|
||||
|
||||
Context "Remote use: By default, don't get format data requiring v5.1+ for v5.0- clients" {
|
||||
BeforeAll {
|
||||
# Simulated PSSenderInfo instances for various PowerShell versions.
|
||||
$pssiV50 = [System.Management.Automation.Internal.InternalTestHooks]::GetCustomPSSenderInfo('foo', [version] '5.0')
|
||||
$pssiV51 = [System.Management.Automation.Internal.InternalTestHooks]::GetCustomPSSenderInfo('foo', [version] '5.1')
|
||||
$pssiV70 = [System.Management.Automation.Internal.InternalTestHooks]::GetCustomPSSenderInfo('foo', [version] '7.0')
|
||||
$cmds = @(
|
||||
@{ shouldBeNull = $true; cmd = { $PSSenderInfo = $pssiV50; Get-FormatData System.IO.FileInfo } }
|
||||
@{ shouldBeNull = $false; cmd = { $PSSenderInfo = $pssiV51; Get-FormatData System.IO.FileInfo } }
|
||||
@{ shouldBeNull = $false; cmd = { $PSSenderInfo = $pssiV70; Get-FormatData System.IO.FileInfo } }
|
||||
)
|
||||
}
|
||||
It "When remoting, <cmd> should return <shouldBeNull> for a null-output test" -TestCases $cmds {
|
||||
param([scriptblock] $cmd, [bool] $shouldBeNull)
|
||||
$null -eq $(& $cmd) | Should -Be $shouldBeNull
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user