Skip to content

Commit 9bea6a9

Browse files
committed
Fix the TranscribeOnly bug (take three)
1 parent c333b3d commit 9bea6a9

File tree

7 files changed

+37
-69
lines changed

7 files changed

+37
-69
lines changed

src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs

+2-22
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ namespace Microsoft.PowerShell.EditorServices.Hosting
3232
public sealed class EditorServicesLoader : IDisposable
3333
{
3434
#if !CoreCLR
35+
// TODO: Well, we're saying we need 4.8 here but we're building for 4.6.2...
3536
// See https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed
3637
private const int Net48Version = 528040;
3738

@@ -342,7 +343,7 @@ private void LogHostInformation()
342343
_logger.Log(PsesLogLevel.Verbose, $@"
343344
== Environment Details ==
344345
- OS description: {RuntimeInformation.OSDescription}
345-
- OS architecture: {GetOSArchitecture()}
346+
- OS architecture: {RuntimeInformation.OSArchitecture}
346347
- Process bitness: {(Environment.Is64BitProcess ? "64" : "32")}
347348
");
348349
}
@@ -355,27 +356,6 @@ private static string GetPSOutputEncoding()
355356
useLocalScope: true).Invoke<string>()[0];
356357
}
357358

358-
// TODO: Deduplicate this with VersionUtils.
359-
private static string GetOSArchitecture()
360-
{
361-
#if CoreCLR
362-
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
363-
{
364-
return RuntimeInformation.OSArchitecture.ToString();
365-
}
366-
#endif
367-
368-
// If on win7 (version 6.1.x), avoid System.Runtime.InteropServices.RuntimeInformation
369-
if (Environment.OSVersion.Version < new Version(6, 2))
370-
{
371-
return Environment.Is64BitProcess
372-
? "X64"
373-
: "X86";
374-
}
375-
376-
return RuntimeInformation.OSArchitecture.ToString();
377-
}
378-
379359
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2208:Instantiate argument exceptions correctly", Justification = "Checking user-defined configuration")]
380360
private void ValidateConfiguration()
381361
{

src/PowerShellEditorServices.VSCode/PowerShellEditorServices.VSCode.csproj

-4
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@
99
<Configurations>Debug;Release</Configurations>
1010
</PropertyGroup>
1111

12-
<PropertyGroup Condition=" '$(TargetFramework)' != 'net462' ">
13-
<DefineConstants>$(DefineConstants);CoreCLR</DefineConstants>
14-
</PropertyGroup>
15-
1612
<!-- Fail the release build if there are missing public API documentation comments -->
1713
<PropertyGroup>
1814
<WarningsAsErrors>1591,1573,1572</WarningsAsErrors>

src/PowerShellEditorServices/PowerShellEditorServices.csproj

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
<Configurations>Debug;Release</Configurations>
1010
</PropertyGroup>
1111

12-
<PropertyGroup Condition=" '$(TargetFramework)' != 'net462' ">
13-
<DefineConstants>$(DefineConstants);CoreCLR</DefineConstants>
14-
</PropertyGroup>
12+
<!--
13+
Be careful about using CoreCLR as a definition, it doesn't work for most of
14+
our code because the shared libraries target netstandard2.0 and so can't use
15+
a property group condition to define it. It's only available to code under
16+
src/PowerShellEditorServices.Hosting and the tests.
17+
-->
1518

1619
<ItemGroup>
1720
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">

src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousPowerShellTask.cs

+10-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ private IReadOnlyList<TResult> ExecuteNormally(CancellationToken cancellationTok
106106
{
107107
_psCommand.AddOutputCommand();
108108

109-
// Fix the transcription bug!
109+
// Fix the transcription bug! Here we're fixing immediately before the invocation of
110+
// our command, that has had `Out-Default` added to it.
110111
if (!_pwsh.Runspace.RunspaceIsRemote)
111112
{
112113
_psesHost.DisableTranscribeOnly();
@@ -282,6 +283,14 @@ private IReadOnlyList<TResult> ExecuteInDebugger(CancellationToken cancellationT
282283
{
283284
_pwsh.Streams.Error.Clear();
284285
}
286+
287+
// Fix the transcription bug! Since we don't depend on `Out-Default` for
288+
// `ExecuteDebugger`, we fix the bug here so the original invocation (before the
289+
// script is executed) is good to go.
290+
if (!_pwsh.Runspace.RunspaceIsRemote)
291+
{
292+
_psesHost.DisableTranscribeOnly();
293+
}
285294
}
286295

287296
_psesHost.DebugContext.ProcessDebuggerResult(debuggerResult);

src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs

+18-10
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ internal class PsesInternalHost : PSHost, IHostSupportsInteractiveSession, IRuns
3939

4040
private static readonly PropertyInfo s_scriptDebuggerTriggerObjectProperty;
4141

42-
#if !CoreCLR
4342
/// <summary>
4443
/// To workaround a horrid bug where the `TranscribeOnly` field of the PSHostUserInterface
4544
/// can accidentally remain true, we have to use a bunch of reflection so that <see
@@ -62,7 +61,6 @@ internal class PsesInternalHost : PSHost, IHostSupportsInteractiveSession, IRuns
6261
private static readonly PropertyInfo s_executionContextProperty;
6362

6463
private static readonly PropertyInfo s_internalHostProperty;
65-
#endif
6664

6765
private readonly ILoggerFactory _loggerFactory;
6866

@@ -130,7 +128,12 @@ static PsesInternalHost()
130128
"TriggerObject",
131129
BindingFlags.Instance | BindingFlags.NonPublic);
132130

133-
#if !CoreCLR
131+
if (VersionUtils.IsNetCore)
132+
{
133+
// The following reflection methods are only needed for the .NET Framework.
134+
return;
135+
}
136+
134137
PropertyInfo transcribeOnlyProperty = typeof(PSHostUserInterface)
135138
.GetProperty("TranscribeOnly", BindingFlags.NonPublic | BindingFlags.Instance);
136139

@@ -144,12 +147,11 @@ static PsesInternalHost()
144147
s_setTranscribeOnlyDelegate = (Action<PSHostUserInterface, bool>)Delegate.CreateDelegate(
145148
typeof(Action<PSHostUserInterface, bool>), transcribeOnlySetMethod);
146149

147-
s_executionContextProperty = typeof(System.Management.Automation.Runspaces.Runspace)
150+
s_executionContextProperty = typeof(Runspace)
148151
.GetProperty("ExecutionContext", BindingFlags.NonPublic | BindingFlags.Instance);
149152

150153
s_internalHostProperty = s_executionContextProperty.PropertyType
151154
.GetProperty("InternalHost", BindingFlags.NonPublic | BindingFlags.Instance);
152-
#endif
153155
}
154156

155157
public PsesInternalHost(
@@ -544,23 +546,29 @@ public void InvokePSDelegate(string representation, ExecutionOptions executionOp
544546
// This works around a bug in PowerShell 5.1 (that was later fixed) where a running
545547
// transcription could cause output to disappear since the `TranscribeOnly` property was
546548
// accidentally not reset to false.
547-
#pragma warning disable CA1822 // Warning to make it static when it's empty for CoreCLR.
548549
internal void DisableTranscribeOnly()
549-
#pragma warning restore CA1822
550550
{
551-
#if !CoreCLR
551+
if (VersionUtils.IsNetCore)
552+
{
553+
return;
554+
}
555+
552556
// To fix the TranscribeOnly bug, we have to get the internal UI, which involves a lot
553557
// of reflection since we can't always just use PowerShell to execute `$Host.UI`.
554558
s_internalPSHostUserInterface ??=
555559
(s_internalHostProperty.GetValue(
556560
s_executionContextProperty.GetValue(CurrentPowerShell.Runspace))
557-
as PSHost).UI;
561+
as PSHost)?.UI;
562+
563+
if (s_internalPSHostUserInterface is null)
564+
{
565+
return;
566+
}
558567

559568
if (s_getTranscribeOnlyDelegate(s_internalPSHostUserInterface))
560569
{
561570
s_setTranscribeOnlyDelegate(s_internalPSHostUserInterface, false);
562571
}
563-
#endif
564572
}
565573

566574
internal Task LoadHostProfilesAsync(CancellationToken cancellationToken)

src/PowerShellEditorServices/Utility/VersionUtils.cs

+1-25
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,6 @@ internal static class VersionUtils
4242
/// </summary>
4343
public static bool IsPS5 { get; } = PSVersion.Major == 5;
4444

45-
/// <summary>
46-
/// True if we are running in PowerShell Core 6, false otherwise.
47-
/// </summary>
48-
public static bool IsPS6 { get; } = PSVersion.Major == 6;
49-
5045
/// <summary>
5146
/// True if we are running in PowerShell 7, false otherwise.
5247
/// </summary>
@@ -70,7 +65,7 @@ internal static class VersionUtils
7065
/// <summary>
7166
/// The .NET Architecture as a string.
7267
/// </summary>
73-
public static string Architecture { get; } = PowerShellReflectionUtils.GetOSArchitecture();
68+
public static string Architecture { get; } = RuntimeInformation.OSArchitecture.ToString();
7469
}
7570

7671
internal static class PowerShellReflectionUtils
@@ -117,24 +112,5 @@ internal static class PowerShellReflectionUtils
117112
public static string PSVersionString { get; } = s_psCurrentVersionProperty != null
118113
? s_psCurrentVersionProperty.GetValue(null).ToString()
119114
: PSVersion.ToString(3);
120-
121-
public static string GetOSArchitecture()
122-
{
123-
#if CoreCLR
124-
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
125-
{
126-
return RuntimeInformation.OSArchitecture.ToString();
127-
}
128-
#endif
129-
// If on win7 (version 6.1.x), avoid System.Runtime.InteropServices.RuntimeInformation
130-
if (Environment.OSVersion.Version < new Version(6, 2))
131-
{
132-
return Environment.Is64BitProcess
133-
? "X64"
134-
: "X86";
135-
}
136-
137-
return RuntimeInformation.OSArchitecture.ToString();
138-
}
139115
}
140116
}

test/PowerShellEditorServices.Test.E2E/PowerShellEditorServices.Test.E2E.csproj

-4
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@
66
<IsPackable>false</IsPackable>
77
</PropertyGroup>
88

9-
<PropertyGroup Condition=" '$(TargetFramework)' != 'net462' ">
10-
<DefineConstants>$(DefineConstants);CoreCLR</DefineConstants>
11-
</PropertyGroup>
12-
139
<ItemGroup>
1410
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
1511
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />

0 commit comments

Comments
 (0)