Skip to content

Commit f985c3f

Browse files
authored
Fix Regression in RunCommandAsync (#310)
## Description Fix regression in RunCommandAsync. Restore trimmed output for stdout. Restore trimmed errors for non-CLIXML errors. ## Related Issue <!-- Link to any related issues: Fixes #123, Closes #456, Related to #789 --> #308 ## Type of Change <!-- Keep the applicable line(s), delete the rest --> - 🐛 Bug fix ## Checklist <!-- Delete the ones that do not apply to your changes --> - [x] New tests added for new functionality (if applicable) - [x] Tested locally on Windows ## Screenshots / Demo `npx winapp restore --verbose` now prints ``` ... SKIP|Microsoft.WindowsAppRuntime.1.8.msix|Already installed or newer version exists INSTALL|Microsoft.WindowsAppRuntime.DDLM.1.8.msix|Will install SKIP|Microsoft.WindowsAppRuntime.Main.1.8.msix|Already installed or newer version exists SKIP|Microsoft.WindowsAppRuntime.Singleton.1.8.msix|Already installed or newer version exists INSTALLING|1 packages will be installed SUCCESS|Microsoft.WindowsAppRuntime.DDLM.1.8.msix|Installation successful ... ``` Output like this was missing before change. ## Additional Notes <!-- Any additional information that reviewers should know --> ## AI Description <!-- ai-description-start --> This pull request fixes a regression in the `RunCommandAsync` method by restoring the trimmed output for both standard output (stdout) and error output (stderr) streams, improving the command result handling in the CLI. This enhancement ensures that users receive the intended output format when executing restore commands. After this change, the command: ```bash npx winapp restore --verbose ``` will provide clearer output with appropriate success markers included. <!-- ai-description-end -->
1 parent 704c32d commit f985c3f

File tree

2 files changed

+60
-5
lines changed

2 files changed

+60
-5
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) Microsoft Corporation and Contributors. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using WinApp.Cli.Services;
5+
6+
namespace WinApp.Cli.Tests;
7+
8+
[TestClass]
9+
[DoNotParallelize]
10+
public class PowerShellServiceTests() : BaseCommandTests(configPaths: false)
11+
{
12+
[TestMethod]
13+
public async Task RunCommandAsync_WithRestoreStyleStdOut_ShouldReturnStdOut()
14+
{
15+
var service = GetRequiredService<IPowerShellService>();
16+
17+
var (exitCode, output, error) = await service.RunCommandAsync(
18+
"Write-Output 'SKIP|Microsoft.WindowsAppRuntime.1.8.msix|Already installed'; Write-Output 'INSTALLING|2 packages will be installed'",
19+
TestTaskContext,
20+
cancellationToken: TestContext.CancellationToken);
21+
22+
Assert.AreEqual(0, exitCode);
23+
Assert.IsTrue(
24+
output.Contains("SKIP|Microsoft.WindowsAppRuntime.1.8.msix|Already installed", StringComparison.Ordinal),
25+
$"Expected SKIP marker in output. Captured output:\n{output}");
26+
Assert.IsTrue(
27+
output.Contains("INSTALLING|2 packages will be installed", StringComparison.Ordinal),
28+
$"Expected INSTALLING marker in output. Captured output:\n{output}");
29+
Assert.IsTrue(string.IsNullOrWhiteSpace(error));
30+
}
31+
32+
[TestMethod]
33+
public async Task RunCommandAsync_WithRestoreStyleStdErr_ShouldReturnStdErr()
34+
{
35+
var service = GetRequiredService<IPowerShellService>();
36+
37+
var (exitCode, output, error) = await service.RunCommandAsync(
38+
"[Console]::Error.WriteLine('ERROR|Microsoft.WindowsAppRuntime.1.8.msix|Installation failed'); exit 1",
39+
TestTaskContext,
40+
cancellationToken: TestContext.CancellationToken);
41+
42+
Assert.AreNotEqual(0, exitCode);
43+
Assert.IsTrue(string.IsNullOrWhiteSpace(output));
44+
Assert.IsTrue(
45+
error.Contains("ERROR|Microsoft.WindowsAppRuntime.1.8.msix|Installation failed", StringComparison.Ordinal),
46+
$"Expected ERROR marker in stderr. Captured error:\n{error}");
47+
}
48+
}

src/winapp-CLI/WinApp.Cli/Services/PowerShellService.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ static string ToEncodedCommand(string s)
100100
process.StandardInput.Close();
101101

102102
await Task.WhenAll(outTask, errTask);
103-
stdOut = NormalizePowerShellStream(outTask.Result);
104-
stdErr = NormalizePowerShellStream(errTask.Result);
103+
stdOut = outTask.Result.Trim();
104+
stdErr = NormalizePowerShellErrorStream(errTask.Result);
105105
}
106106

107107
await process.WaitForExitAsync(cancellationToken);
@@ -121,18 +121,24 @@ static string ToEncodedCommand(string s)
121121
return (exitCode, stdOut, stdErr);
122122
}
123123

124-
private static string NormalizePowerShellStream(string stream)
124+
private static string NormalizePowerShellErrorStream(string stream)
125125
{
126126
if (string.IsNullOrWhiteSpace(stream))
127127
{
128128
return string.Empty;
129129
}
130130

131131
var trimmed = stream.Trim();
132+
133+
if (!trimmed.Contains("<Objs", StringComparison.OrdinalIgnoreCase))
134+
{
135+
return trimmed;
136+
}
137+
132138
var reasonIndex = trimmed.IndexOf("Reason:", StringComparison.OrdinalIgnoreCase);
133139
if (reasonIndex < 0)
134140
{
135-
return string.Empty;
141+
return trimmed;
136142
}
137143

138144
var reasonStart = reasonIndex + "Reason:".Length;
@@ -153,7 +159,8 @@ private static string NormalizePowerShellStream(string stream)
153159
.Select(line => line.Trim())
154160
.Where(line => !string.IsNullOrWhiteSpace(line));
155161

156-
return string.Join(" ", lines).Trim();
162+
var normalized = string.Join(" ", lines).Trim();
163+
return string.IsNullOrWhiteSpace(normalized) ? trimmed : normalized;
157164
}
158165

159166
private static string StripXmlTags(string value)

0 commit comments

Comments
 (0)