Skip to content

Commit

Permalink
PowerShell code cleanup and partial fix for signaling command failure (
Browse files Browse the repository at this point in the history
…#3150)

* cleanup

* fix one case where CommandFailed isn't sent when pwsh submission fails

This also adds another test case that can't pass until a PowerShell bug is fixed: PowerShell/PowerShell#20079

* use generalized API for requesting input

* update PowerShell package version
  • Loading branch information
jonsequitur committed Aug 25, 2023
1 parent f23f935 commit 2ebbb6a
Show file tree
Hide file tree
Showing 14 changed files with 138 additions and 188 deletions.
4 changes: 2 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

<PropertyGroup>
<MicrosoftNETTestSdkVersion>17.4.0</MicrosoftNETTestSdkVersion>
<NewtonsoftJsonVersion>13.0.2</NewtonsoftJsonVersion>
<NewtonsoftJsonVersion>13.0.3</NewtonsoftJsonVersion>
<MicrosoftCodeAnalysisCommonVersion>4.6.0</MicrosoftCodeAnalysisCommonVersion>
<SystemDrawingCommonVersion>7.0.0</SystemDrawingCommonVersion>
<SystemReactiveVersion>6.0.0</SystemReactiveVersion>
<SystemSecurityCryptographyXmlVersion>7.0.0</SystemSecurityCryptographyXmlVersion>
<SystemSecurityCryptographyXmlVersion>7.0.1</SystemSecurityCryptographyXmlVersion>
<xunitVersion>2.4.2</xunitVersion>
<xunitrunnervisualstudioVersion>2.4.5</xunitrunnervisualstudioVersion>
</PropertyGroup>
Expand Down
1 change: 0 additions & 1 deletion src/Microsoft.DotNet.Interactive.Formatting/Formatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.DotNet.Interactive.CSharp;
using Microsoft.DotNet.Interactive.Formatting.Csv;
using Microsoft.DotNet.Interactive.Formatting.TabularData;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Microsoft.DotNet.Interactive.Tests.Utility;
using Xunit;
using Xunit.Abstractions;
using Language = Microsoft.DotNet.Interactive.Tests.Language;

namespace Microsoft.DotNet.Interactive.PowerShell.Tests;

Expand Down Expand Up @@ -68,6 +69,26 @@ public async Task PowerShell_progress_sends_updated_display_values()
e => e.Should().BeOfType<CommandSucceeded>());
}

[Fact(Skip = "Waiting for a fix for https://github.com/PowerShell/PowerShell/issues/20079")]
public async Task When_command_is_not_recognized_then_the_command_fails()
{
using var kernel = CreateKernel(Language.PowerShell);

var result = await kernel.SendAsync(new SubmitCode("oops"));

result.Events.Last().Should().BeOfType<CommandFailed>();
}

[Fact]
public async Task When_code_produces_errors_then_the_command_fails()
{
using var kernel = CreateKernel(Language.PowerShell);

var result = await kernel.SendAsync(new SubmitCode("Get-ChildItem oops"));

result.Events.Last().Should().BeOfType<CommandFailed>();
}

[Fact]
public async Task PowerShell_token_variables_work()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using System.Collections.Generic;
using System.IO;
using System.IO.Pipelines;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;

namespace Microsoft.DotNet.Interactive.PowerShell.Host;

internal class ConsoleColorProxy
{
private readonly PSKernelHostUserInterface _ui;

public ConsoleColorProxy(PSKernelHostUserInterface ui)
{
_ui = ui ?? throw new ArgumentNullException(nameof(ui));
}

public ConsoleColor FormatAccentColor
{
get => _ui.FormatAccentColor;
set => _ui.FormatAccentColor = value;
}

public ConsoleColor ErrorAccentColor
{
get => _ui.ErrorAccentColor;
set => _ui.ErrorAccentColor = value;
}

public ConsoleColor ErrorForegroundColor
{
get => _ui.ErrorForegroundColor;
set => _ui.ErrorForegroundColor = value;
}

public ConsoleColor ErrorBackgroundColor
{
get => _ui.ErrorBackgroundColor;
set => _ui.ErrorBackgroundColor = value;
}

public ConsoleColor WarningForegroundColor
{
get => _ui.WarningForegroundColor;
set => _ui.WarningForegroundColor = value;
}

public ConsoleColor WarningBackgroundColor
{
get => _ui.WarningBackgroundColor;
set => _ui.WarningBackgroundColor = value;
}

public ConsoleColor DebugForegroundColor
{
get => _ui.DebugForegroundColor;
set => _ui.DebugForegroundColor = value;
}

public ConsoleColor DebugBackgroundColor
{
get => _ui.DebugBackgroundColor;
set => _ui.DebugBackgroundColor = value;
}

public ConsoleColor VerboseForegroundColor
{
get => _ui.VerboseForegroundColor;
set => _ui.VerboseForegroundColor = value;
}

public ConsoleColor VerboseBackgroundColor
{
get => _ui.VerboseBackgroundColor;
set => _ui.VerboseBackgroundColor = value;
}

public ConsoleColor ProgressForegroundColor
{
get => _ui.ProgressForegroundColor;
set => _ui.ProgressForegroundColor = value;
}

public ConsoleColor ProgressBackgroundColor
{
get => _ui.ProgressBackgroundColor;
set => _ui.ProgressBackgroundColor = value;
}
}
97 changes: 6 additions & 91 deletions src/Microsoft.DotNet.Interactive.PowerShell/Host/PSKernelHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,28 @@ public class PSKernelHost : PSHost, IHostSupportsInteractiveSession
private readonly PowerShellKernel _powerShell;
private const string HostName = ".NET Interactive Host";

private readonly Version _hostVersion;
private readonly Guid _instanceId;
private readonly PSKernelHostUserInterface _ui;
private readonly PSObject _consoleColorProxy;

internal PSKernelHost(PowerShellKernel powerShell)
{
_powerShell = powerShell ?? throw new ArgumentNullException(nameof(powerShell));
_hostVersion = new Version("1.0.0");
_instanceId = Guid.NewGuid();
Version = new Version("1.0.0");
InstanceId = Guid.NewGuid();
_ui = new PSKernelHostUserInterface(_powerShell);
_consoleColorProxy = PSObject.AsPSObject(new ConsoleColorProxy(_ui));
PrivateData = PSObject.AsPSObject(new ConsoleColorProxy(_ui));
}

#region "PSHost Implementation"

public override string Name => HostName;

public override Guid InstanceId => this._instanceId;
public override Guid InstanceId { get; }

public override Version Version => _hostVersion;
public override Version Version { get; }

public override PSHostUserInterface UI => _ui;

public override PSObject PrivateData => _consoleColorProxy;
public override PSObject PrivateData { get; }

public override CultureInfo CurrentCulture => CultureInfo.CurrentCulture;

Expand Down Expand Up @@ -88,86 +85,4 @@ public void PushRunspace(Runspace runspace)
}

#endregion
}

internal class ConsoleColorProxy
{
private readonly PSKernelHostUserInterface _ui;

public ConsoleColorProxy(PSKernelHostUserInterface ui)
{
_ui = ui ?? throw new ArgumentNullException(nameof(ui));
}

public ConsoleColor FormatAccentColor
{
get => _ui.FormatAccentColor;
set => _ui.FormatAccentColor = value;
}

public ConsoleColor ErrorAccentColor
{
get => _ui.ErrorAccentColor;
set => _ui.ErrorAccentColor = value;
}

public ConsoleColor ErrorForegroundColor
{
get => _ui.ErrorForegroundColor;
set => _ui.ErrorForegroundColor = value;
}

public ConsoleColor ErrorBackgroundColor
{
get => _ui.ErrorBackgroundColor;
set => _ui.ErrorBackgroundColor = value;
}

public ConsoleColor WarningForegroundColor
{
get => _ui.WarningForegroundColor;
set => _ui.WarningForegroundColor = value;
}

public ConsoleColor WarningBackgroundColor
{
get => _ui.WarningBackgroundColor;
set => _ui.WarningBackgroundColor = value;
}

public ConsoleColor DebugForegroundColor
{
get => _ui.DebugForegroundColor;
set => _ui.DebugForegroundColor = value;
}

public ConsoleColor DebugBackgroundColor
{
get => _ui.DebugBackgroundColor;
set => _ui.DebugBackgroundColor = value;
}

public ConsoleColor VerboseForegroundColor
{
get => _ui.VerboseForegroundColor;
set => _ui.VerboseForegroundColor = value;
}

public ConsoleColor VerboseBackgroundColor
{
get => _ui.VerboseBackgroundColor;
set => _ui.VerboseBackgroundColor = value;
}

public ConsoleColor ProgressForegroundColor
{
get => _ui.ProgressForegroundColor;
set => _ui.ProgressForegroundColor = value;
}

public ConsoleColor ProgressBackgroundColor
{
get => _ui.ProgressBackgroundColor;
set => _ui.ProgressBackgroundColor = value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ private string ReadInput(string prompt)
return _powerShellKernel.ReadInput(prompt);
}

throw new InvalidOperationException($"'{nameof(ReadInput)}' should be called from PowerShell kernel.");
var result = Kernel.GetInputAsync(prompt).GetAwaiter().GetResult();
return result;
}

private PasswordString ReadPassword(string prompt)
Expand All @@ -79,7 +80,8 @@ private PasswordString ReadPassword(string prompt)
return _powerShellKernel.ReadPassword(prompt);
}

throw new InvalidOperationException($"'{nameof(ReadPassword)}' should be called from PowerShell kernel.");
var result = Kernel.GetPasswordAsync(prompt).GetAwaiter().GetResult();
return new PasswordString(result);
}

public override string ReadLine()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
<ItemGroup>
<PackageReference Include="System.IO.Pipelines" Version="7.0.0" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="$(SystemSecurityCryptographyXmlVersion)" />
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.3.0" />
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.3.6" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,83 +1,25 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Security;
using System.Threading.Tasks;

namespace Microsoft.DotNet.Interactive.PowerShell;

using System.Management.Automation;

internal static class PowerShellExtensions
{
private static PSInvocationSettings _settings = new() { AddToHistory = true };

public static void InvokeAndClearCommands(this PowerShell pwsh)
private static readonly PSInvocationSettings _settings = new()
{
try
{
pwsh.Invoke(input: null, _settings);
}
finally
{
pwsh.Streams.ClearStreams();
pwsh.Commands.Clear();
}
}
AddToHistory = true
};

public static async Task InvokeAndClearCommandsAsync(this PowerShell pwsh)
{
try
{
await pwsh.InvokeAsync<PSObject>(
input: null,
settings: _settings,
callback: null,
state: null).ConfigureAwait(false);
}
finally
{
pwsh.Streams.ClearStreams();
pwsh.Commands.Clear();
}
}

public static void InvokeAndClearCommands(this PowerShell pwsh, IEnumerable input)
{
try
{
pwsh.Invoke(input, _settings);
}
finally
{
pwsh.Streams.ClearStreams();
pwsh.Commands.Clear();
}
}

public static Collection<T> InvokeAndClearCommands<T>(this PowerShell pwsh)
{
try
{
var result = pwsh.Invoke<T>(input: null, settings: _settings);
return result;
}
finally
{
pwsh.Streams.ClearStreams();
pwsh.Commands.Clear();
}
}

public static Collection<T> InvokeAndClearCommands<T>(this PowerShell pwsh, IEnumerable input)
public static void InvokeAndClearCommands(this PowerShell pwsh)
{
try
{
var result = pwsh.Invoke<T>(input, _settings);
return result;
pwsh.Invoke(input: null, settings: _settings);
}
finally
{
Expand Down
Loading

0 comments on commit 2ebbb6a

Please sign in to comment.