Skip to content

Commit 65f9deb

Browse files
committed
Restart ExternalScriptingShell process if exited. Add Ctrl + Q shortcut to clear terminal output.
1 parent bcaaed8 commit 65f9deb

File tree

2 files changed

+68
-63
lines changed

2 files changed

+68
-63
lines changed

Agent/Services/ExternalScriptingShell.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ public ExternalScriptingShell(ConfigService configService)
4848

4949
public static ExternalScriptingShell GetCurrent(ScriptingShell shell, string senderConnectionId)
5050
{
51-
if (_sessions.TryGetValue($"{shell}-{senderConnectionId}", out var session))
51+
if (_sessions.TryGetValue($"{shell}-{senderConnectionId}", out var session) &&
52+
session.ShellProcess?.HasExited != true)
5253
{
5354
session.ProcessIdleTimeout.Stop();
5455
session.ProcessIdleTimeout.Start();

Server/Components/Devices/Terminal.razor.cs

+66-62
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,10 @@ public partial class Terminal : AuthComponentBase, IDisposable
2323
private int _lastCursorIndex;
2424
private ScriptingShell _shell;
2525

26-
private string _terminalOpenClass;
27-
2826
private ElementReference _terminalInput;
27+
private string _terminalOpenClass;
2928
private ElementReference _terminalWindow;
3029

31-
[Inject]
32-
private IModalService ModalService { get; set; }
33-
3430
[Inject]
3531
private IClientAppState AppState { get; set; }
3632

@@ -40,9 +36,6 @@ public partial class Terminal : AuthComponentBase, IDisposable
4036
[Inject]
4137
private IDataService DataService { get; set; }
4238

43-
[Inject]
44-
private ILogger<Terminal> Logger { get; set; }
45-
4639
private string InputText
4740
{
4841
get => _inputText;
@@ -59,6 +52,33 @@ private string InputText
5952
[Inject]
6053
private IJsInterop JsInterop { get; set; }
6154

55+
[Inject]
56+
private ILogger<Terminal> Logger { get; set; }
57+
58+
[Inject]
59+
private IModalService ModalService { get; set; }
60+
private EventCallback<SavedScript> RunQuickScript =>
61+
EventCallback.Factory.Create<SavedScript>(this, async script =>
62+
{
63+
var scriptRun = new ScriptRun()
64+
{
65+
OrganizationID = User.OrganizationID,
66+
RunAt = Time.Now,
67+
SavedScriptId = script.Id,
68+
RunOnNextConnect = false,
69+
Initiator = User.UserName,
70+
InputType = ScriptInputType.OneTimeScript
71+
};
72+
73+
scriptRun.Devices = DataService.GetDevices(AppState.DevicesFrameSelectedDevices);
74+
75+
await DataService.AddScriptRun(scriptRun);
76+
77+
await CircuitConnection.RunScript(AppState.DevicesFrameSelectedDevices, script.Id, scriptRun.Id, ScriptInputType.OneTimeScript, false);
78+
79+
ToastService.ShowToast($"Running script on {scriptRun.Devices.Count} devices.");
80+
});
81+
6282
[Inject]
6383
private IToastService ToastService { get; set; }
6484

@@ -69,13 +89,6 @@ public void Dispose()
6989
GC.SuppressFinalize(this);
7090
}
7191

72-
protected override async Task OnInitializedAsync()
73-
{
74-
await base.OnInitializedAsync();
75-
CircuitConnection.MessageReceived += CircuitConnection_MessageReceived;
76-
AppState.PropertyChanged += AppState_PropertyChanged;
77-
}
78-
7992
protected override Task OnAfterRenderAsync(bool firstRender)
8093
{
8194
if (firstRender)
@@ -85,6 +98,12 @@ protected override Task OnAfterRenderAsync(bool firstRender)
8598
return base.OnAfterRenderAsync(firstRender);
8699
}
87100

101+
protected override async Task OnInitializedAsync()
102+
{
103+
await base.OnInitializedAsync();
104+
CircuitConnection.MessageReceived += CircuitConnection_MessageReceived;
105+
AppState.PropertyChanged += AppState_PropertyChanged;
106+
}
88107
private void ApplyCompletion(PwshCommandCompletion completion)
89108
{
90109
try
@@ -172,25 +191,6 @@ private void EvaluateInputKeypress(KeyboardEventArgs ev)
172191
}
173192
}
174193

175-
private void ShowTerminalHelp()
176-
{
177-
ModalService.ShowModal("Terminal Help", new[]
178-
{
179-
"Enter terminal commands that will execute on all selected devices.",
180-
181-
"Tab completion is available for PowerShell Core (PSCore) and Windows PowerShell (WinPS). Tab and Shift + Tab " +
182-
"will cycle through potential completions. Ctrl + Space will show all available completions.",
183-
184-
"If more than one devices is selected, the first device's file system will be used when " +
185-
"auto-completing file and directory paths.",
186-
187-
"PowerShell Core is cross-platform and is available on all client operating systems. Bash is available " +
188-
"on Windows 10 if WSL (Windows Subsystem for Linux) is installed.",
189-
190-
"Note: The first PS Core command or tab completion takes a few moments while the service is " +
191-
"starting on the remote device."
192-
});
193-
}
194194
private async Task EvaluateKeyDown(KeyboardEventArgs ev)
195195
{
196196
if (!ev.Key.Equals("Tab", StringComparison.OrdinalIgnoreCase) &&
@@ -238,6 +238,11 @@ private async Task EvaluateKeyDown(KeyboardEventArgs ev)
238238

239239
await ShowAllCompletions();
240240
}
241+
else if (ev.CtrlKey && ev.Key.Equals("q", StringComparison.OrdinalIgnoreCase))
242+
{
243+
AppState.TerminalLines.Clear();
244+
AppState.InvokePropertyChanged(nameof(AppState.TerminalLines));
245+
}
241246
}
242247

243248
private async Task GetNextCompletion(bool forward)
@@ -261,17 +266,6 @@ private async Task ShowAllCompletions()
261266

262267
await CircuitConnection.GetPowerShellCompletions(_lastCompletionInput, _lastCursorIndex, CompletionIntent.ShowAll, false);
263268
}
264-
private void ToggleTerminalOpen()
265-
{
266-
if (string.IsNullOrWhiteSpace(_terminalOpenClass))
267-
{
268-
_terminalOpenClass = "open";
269-
}
270-
else
271-
{
272-
_terminalOpenClass = string.Empty;
273-
}
274-
}
275269

276270
private async Task ShowQuickScripts()
277271
{
@@ -288,7 +282,7 @@ private async Task ShowQuickScripts()
288282
return;
289283
}
290284

291-
285+
292286
void showModal(RenderTreeBuilder builder)
293287
{
294288
builder.OpenComponent<QuickScriptsSelector>(0);
@@ -300,28 +294,38 @@ void showModal(RenderTreeBuilder builder)
300294
await ModalService.ShowModal("Quick Scripts", showModal);
301295
}
302296

303-
private EventCallback<SavedScript> RunQuickScript =>
304-
EventCallback.Factory.Create<SavedScript>(this, async script =>
297+
private void ShowTerminalHelp()
298+
{
299+
ModalService.ShowModal("Terminal Help", new[]
305300
{
306-
var scriptRun = new ScriptRun()
307-
{
308-
OrganizationID = User.OrganizationID,
309-
RunAt = Time.Now,
310-
SavedScriptId = script.Id,
311-
RunOnNextConnect = false,
312-
Initiator = User.UserName,
313-
InputType = ScriptInputType.OneTimeScript
314-
};
301+
"Enter terminal commands that will execute on all selected devices.",
315302

316-
scriptRun.Devices = DataService.GetDevices(AppState.DevicesFrameSelectedDevices);
303+
"Tab completion is available for PowerShell Core (PSCore) and Windows PowerShell (WinPS). Tab and Shift + Tab " +
304+
"will cycle through potential completions. Ctrl + Space will show all available completions.",
317305

318-
await DataService.AddScriptRun(scriptRun);
306+
"If more than one devices is selected, the first device's file system will be used when " +
307+
"auto-completing file and directory paths.",
319308

320-
await CircuitConnection.RunScript(AppState.DevicesFrameSelectedDevices, script.Id, scriptRun.Id, ScriptInputType.OneTimeScript, false);
309+
"PowerShell Core is cross-platform and is available on all client operating systems. Bash is available " +
310+
"on Windows 10 if WSL (Windows Subsystem for Linux) is installed.",
321311

322-
ToastService.ShowToast($"Running script on {scriptRun.Devices.Count} devices.");
323-
});
312+
"Up and down arrow keys will cycle through terminal input history. Ctrl + Q will clear the output window.",
324313

314+
"Note: The first PS Core command or tab completion takes a few moments while the service is " +
315+
"starting on the remote device."
316+
});
317+
}
318+
private void ToggleTerminalOpen()
319+
{
320+
if (string.IsNullOrWhiteSpace(_terminalOpenClass))
321+
{
322+
_terminalOpenClass = "open";
323+
}
324+
else
325+
{
326+
_terminalOpenClass = string.Empty;
327+
}
328+
}
325329
private bool TryMatchShellShortcuts()
326330
{
327331
var currentText = InputText?.Trim()?.ToLower();

0 commit comments

Comments
 (0)