Skip to content

Commit d72182e

Browse files
authored
Merge PR #11 Associate output with commands
Associates output with commands so that they are paired together and it's easier to determine if everything succeeded or not
2 parents 804967a + 8373b71 commit d72182e

16 files changed

Lines changed: 412 additions & 281 deletions

.github/workflows/build-gate.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@ on:
55
branches: [ '*' ]
66

77
env:
8-
BUILD_VERSION: 0.1.${{github.run_number}}
8+
BUILD_VERSION: 0.2.${{github.run_number}}
99
SLN_PATH: src/ShellRunner.sln
10-
TEST_PATH: src/TestApp/bin/Release/net6.0/TestApp.dll
10+
TEST_PATH: src/TestApp/bin/Release/net8.0/TestApp.dll
1111

1212
jobs:
1313
build:
1414
runs-on: ubuntu-latest
1515

1616
steps:
17-
- uses: actions/checkout@v2
17+
- uses: actions/checkout@v4
1818
- name: Setup .NET
19-
uses: actions/setup-dotnet@v1
19+
uses: actions/setup-dotnet@v4
2020
with:
21-
dotnet-version: 6.0.x
21+
dotnet-version: 8.0.x
2222

2323
- name: Restore dependencies
2424
run: dotnet restore $SLN_PATH
@@ -30,7 +30,7 @@ jobs:
3030
-p:Version=$BUILD_VERSION
3131

3232
- name: Upload ShellRunner Build Artifacts
33-
uses: actions/upload-artifact@v2
33+
uses: actions/upload-artifact@v4.6.1
3434
with:
3535
name: BuildArtifacts
3636
path: ./**/bin/Release/**/*
@@ -42,10 +42,10 @@ jobs:
4242
steps:
4343

4444
- name: Download artifacts
45-
uses: actions/download-artifact@v2
45+
uses: actions/download-artifact@v4.1.9
4646
with:
4747
name: BuildArtifacts
4848

4949
- name: Test
50-
run: dotnet $TEST_PATH
50+
run: dotnet $TEST_PATH bash
5151

.github/workflows/build.yml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ on:
55
branches: [ "stable" ]
66

77
env:
8-
BUILD_VERSION: 0.1.${{github.run_number}}
8+
BUILD_VERSION: 0.2.${{github.run_number}}
99
SLN_PATH: src/ShellRunner.sln
10-
TEST_PATH: src/TestApp/bin/Release/net6.0/TestApp.dll
10+
TEST_PATH: src/TestApp/bin/Release/net8.0/TestApp.dll
1111
PROJECT_PATH: src/ShellRunner/ShellRunner.csproj
1212
PRE_RELEASE_ARTIFACTS: ./**/ShellRunner.$BUILD_VERSION-alpha.nupkg
1313
RELEASE_ARTIFACTS: ./**/ShellRunner.$BUILD_VERSION.nupkg
@@ -17,11 +17,11 @@ jobs:
1717
runs-on: ubuntu-latest
1818

1919
steps:
20-
- uses: actions/checkout@v3
20+
- uses: actions/checkout@v4
2121
- name: Setup .NET
22-
uses: actions/setup-dotnet@v2
22+
uses: actions/setup-dotnet@v4
2323
with:
24-
dotnet-version: 6.0.x
24+
dotnet-version: 8.0.x
2525

2626
- name: Restore dependencies
2727
run: dotnet restore $SLN_PATH
@@ -33,7 +33,7 @@ jobs:
3333
-p:Version=$BUILD_VERSION
3434

3535
- name: Test
36-
run: dotnet $TEST_PATH
36+
run: dotnet $TEST_PATH bash
3737

3838
- name: Pack-Alpha
3939
run: dotnet pack $PROJECT_PATH
@@ -50,13 +50,13 @@ jobs:
5050
-p:PackageVersion=$BUILD_VERSION
5151

5252
- name: Upload ShellRunner PreRelease Artifacts
53-
uses: actions/upload-artifact@v2
53+
uses: actions/upload-artifact@v4.6.1
5454
with:
5555
name: PreReleaseArtifacts
5656
path: $PRE_RELEASE_ARTIFACTS
5757

5858
- name: Upload ShellRunner Release Artifacts
59-
uses: actions/upload-artifact@v2
59+
uses: actions/upload-artifact@v4.6.1
6060
with:
6161
name: ReleaseArtifacts
6262
path: $RELEASE_ARTIFACTS
@@ -70,7 +70,7 @@ jobs:
7070
steps:
7171

7272
- name: Download artifacts
73-
uses: actions/download-artifact@v2
73+
uses: actions/download-artifact@v4.1.9
7474
with:
7575
name: PreReleaseArtifacts
7676

@@ -87,7 +87,7 @@ jobs:
8787
steps:
8888

8989
- name: Download artifacts
90-
uses: actions/download-artifact@v2
90+
uses: actions/download-artifact@v4.1.9
9191
with:
9292
name: ReleaseArtifacts
9393

README.md

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,47 @@
11
# ShellRunner
22

3-
Run command line tools inside CSharp.
3+
Run command line tools using CSharp.
4+
5+
Supports Windows and Linux (Powershell, bash, and cmd).
46

57
Example running some dotnet CLI commands:
68

79
```csharp
810
using ShellRunner;
911

10-
CommandRunner
12+
CommandBuilder cb = await CommandRunner
1113
.UsePowershell()
1214
.StartProcess()
1315
// print the dotnet info command
1416
.AddCommand("dotnet --info")
1517
// build a csharp project
16-
.AddCommand("cd C:\\source\\repos\\MyProject")
17-
.AddCommand("dotnet build MyProject.sln -c Release")
18-
// Print the output
19-
.AddCommand("cd bin\\Release")
20-
.AddCommand("Get-ChildItem -r")
21-
.Run();
18+
.AddCommand(@"cd C:\source\repos\MyProject")
19+
.AddCommand("dotnet build MyProject.sln -c Release", key: "build-output")
20+
// Print the file list
21+
.AddCommand(@"cd bin\Release\net8.0")
22+
.AddCommand("Get-ChildItem -r", key: "files")
23+
.RunAsync();
2224
```
2325

2426
Shell Runner is really useful to create a wrapper for several other
25-
commands and to work with data before or after you run the commands.
27+
commands and to work with data before or after you run the commands.
28+
29+
After running the commands you can optionally access the output of each command
30+
separately so you know the result of each command specifically.
31+
32+
```csharp
33+
Console.WriteLine("Outputs:");
34+
35+
// the outputs are organized by command
36+
foreach (var cmd in cb.Commands)
37+
foreach(var output in cmd.Output)
38+
Console.WriteLine(" " + output.Data);
39+
40+
// OR use keys declared above
41+
var buildCmd = cb.GetCommand("build-output").Output;
42+
43+
Console.ForegroundColor = ConsoleColor.Blue;
44+
45+
foreach(var output in buildCmd)
46+
Console.WriteLine(" " + output.Data);
47+
```

src/ShellRunner/CommandBuilder.cs

Lines changed: 52 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,89 @@
1-
using System;
2-
using System.Diagnostics;
1+
using System.Diagnostics;
32

43
namespace ShellRunner;
4+
55
public class CommandBuilder
66
{
7-
CommandBuilderOptions _options;
7+
CommandBuilderOptions options;
8+
List<ProcessCommand> commands;
9+
Dictionary<string, ProcessCommand> commandMap;
810

911
public ProcessStartInfo StartInfo { get; set; }
1012
public Process Process { get; set; }
13+
public IReadOnlyList<IProcessedCommand> Commands => commands.AsReadOnly();
1114

1215
internal CommandBuilder(CommandBuilderOptions options, Process process)
1316
{
1417
Process = process;
1518

16-
Commands = new List<ProcessCommand>();
17-
18-
_options = options;
19+
commands = new List<ProcessCommand>();
20+
this.commandMap = new Dictionary<string, ProcessCommand>();
21+
22+
this.options = options;
1923

2024
StartInfo = new ProcessStartInfo
2125
{
22-
FileName = options.File,
23-
Arguments = options.Args,
26+
FileName = this.options.File,
27+
Arguments = this.options.Args,
2428
CreateNoWindow = true,
2529
WindowStyle = ProcessWindowStyle.Hidden,
2630
UseShellExecute = false,
27-
RedirectStandardOutput = options.RedirectStandardOutput,
28-
RedirectStandardError = options.RedirectStandardError,
29-
RedirectStandardInput = options.RedirectStandardInput
31+
RedirectStandardOutput = this.options.RedirectStandardOutput,
32+
RedirectStandardError = this.options.RedirectStandardError,
33+
RedirectStandardInput = this.options.RedirectStandardInput
3034
};
3135
}
3236

33-
public List<ProcessCommand> Commands { get; private set; }
34-
35-
public CommandBuilder AddWorkingDirectory(string workingDirectory)
37+
/// <summary>
38+
/// Add a command to the command list.
39+
/// </summary>
40+
/// <param name="command"></param>
41+
/// <exception cref="ArgumentException">When a duplicate key is added.</exception>
42+
public void AddCommand(ProcessCommand command)
3643
{
37-
StartInfo.WorkingDirectory = workingDirectory;
38-
return this;
44+
this.commands.Add(command);
45+
46+
if(this.commandMap.ContainsKey(command.Key))
47+
throw new ArgumentException($"Command with key \"{command.Key}\" already exists.");
48+
49+
this.commandMap.Add(command.Key, command);
3950
}
4051

41-
private void Proc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
52+
/// <summary>
53+
/// Get a specific command by key.
54+
/// </summary>
55+
/// <param name="key">The key for the command ran earlier.</param>
56+
/// <returns></returns>
57+
/// <exception cref="KeyNotFoundException">When a key isn't present in the dictionary.</exception>
58+
public IProcessedCommand GetCommand(string key)
4259
{
4360
try
4461
{
45-
if (e.Data is null)
46-
return;
47-
48-
var fg = Console.ForegroundColor;
49-
Console.ForegroundColor = ConsoleColor.Yellow;
50-
Console.WriteLine($"Error: {e.Data}");
51-
Console.ForegroundColor = fg;
62+
return this.commandMap[key];
5263
}
53-
catch(Exception ex)
64+
catch (KeyNotFoundException)
5465
{
55-
var fg = Console.ForegroundColor;
56-
Console.ForegroundColor = ConsoleColor.Red;
57-
Console.WriteLine("Error while processing error data.");
58-
Console.WriteLine(ex);
59-
Console.ForegroundColor = fg;
66+
throw new KeyNotFoundException($"Command with key \"{key}\" not found.");
6067
}
6168
}
6269

63-
private void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
70+
public CommandBuilder AddWorkingDirectory(string workingDirectory)
6471
{
65-
try
66-
{
67-
Console.WriteLine(e.Data);
68-
}
69-
catch (Exception ex)
72+
StartInfo.WorkingDirectory = workingDirectory;
73+
return this;
74+
}
75+
76+
public async Task<CommandBuilder> RunAsync(CancellationToken cancellationToken = default)
77+
{
78+
foreach(var command in commands)
7079
{
71-
var fg = Console.ForegroundColor;
72-
Console.ForegroundColor = ConsoleColor.Red;
73-
Console.WriteLine("Error while processing output data.");
74-
Console.WriteLine(ex);
75-
Console.ForegroundColor = fg;
80+
if (cancellationToken.IsCancellationRequested)
81+
break;
82+
83+
await command.RunCommandAsync(this.Process, cancellationToken);
7684
}
85+
86+
return this;
7787
}
88+
7889
}

src/ShellRunner/CommandBuilderOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace ShellRunner;
44

5+
[DebuggerDisplay("{Shell} {File} {Args}")]
56
public record CommandBuilderOptions
67
{
78
public CommandBuilderOptions(ShellType shellType, string file, string args)

src/ShellRunner/CommandOutput.cs

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)