@@ -69,7 +69,7 @@ public List<Result> LoadContextMenus(Result selectedResult)
69
69
private static readonly JsonSerializerOptions options = new ( )
70
70
{
71
71
PropertyNameCaseInsensitive = true ,
72
- #pragma warning disable SYSLIB0020
72
+ #pragma warning disable SYSLIB0020
73
73
// IgnoreNullValues is obsolete, but the replacement JsonIgnoreCondition.WhenWritingNull still
74
74
// deserializes null, instead of ignoring it and leaving the default (empty list). We can change the behaviour
75
75
// to accept null and fallback to a default etc, or just keep IgnoreNullValues for now
@@ -247,74 +247,75 @@ protected string Execute(ProcessStartInfo startInfo)
247
247
248
248
protected async Task < Stream > ExecuteAsync ( ProcessStartInfo startInfo , CancellationToken token = default )
249
249
{
250
- Process process = null ;
251
- using var exitTokenSource = new CancellationTokenSource ( ) ;
252
- try
250
+ using var process = Process . Start ( startInfo ) ;
251
+ if ( process == null )
253
252
{
254
- process = Process . Start ( startInfo ) ;
255
- if ( process == null )
256
- {
257
- Log . Error ( "|JsonRPCPlugin.ExecuteAsync|Can't start new process" ) ;
258
- return Stream . Null ;
259
- }
260
-
253
+ Log . Error ( "|JsonRPCPlugin.ExecuteAsync|Can't start new process" ) ;
254
+ return Stream . Null ;
255
+ }
261
256
262
- await using var source = process . StandardOutput . BaseStream ;
263
257
264
- var buffer = BufferManager . GetStream ( ) ;
265
258
266
- token . Register ( ( ) =>
267
- {
268
- // ReSharper disable once AccessToModifiedClosure
269
- // Manually Check whether disposed
270
- if ( ! exitTokenSource . IsCancellationRequested && ! process . HasExited )
271
- process . Kill ( ) ;
272
- } ) ;
259
+ var sourceBuffer = BufferManager . GetStream ( ) ;
260
+ var errorBuffer = BufferManager . GetStream ( ) ;
273
261
262
+ var sourceCopyTask = process . StandardOutput . BaseStream . CopyToAsync ( sourceBuffer , token ) ;
263
+ var errorCopyTask = process . StandardError . BaseStream . CopyToAsync ( errorBuffer , token ) ;
264
+
265
+ token . Register ( ( ) =>
266
+ {
274
267
try
275
268
{
276
- // token expire won't instantly trigger the exception,
277
- // manually kill process at before
278
- await source . CopyToAsync ( buffer , token ) ;
269
+ if ( ! process . HasExited )
270
+ process . Kill ( ) ;
279
271
}
280
- catch ( OperationCanceledException )
272
+ catch ( InvalidOperationException )
281
273
{
282
- await buffer . DisposeAsync ( ) ;
283
- return Stream . Null ;
284
274
}
275
+ } ) ;
285
276
286
- buffer . Seek ( 0 , SeekOrigin . Begin ) ;
287
-
288
- token . ThrowIfCancellationRequested ( ) ;
277
+ try
278
+ {
279
+ // token expire won't instantly trigger the exception,
280
+ // manually kill process at before
281
+ await process . WaitForExitAsync ( token ) ;
282
+ await Task . WhenAll ( sourceCopyTask , errorCopyTask ) ;
283
+ }
284
+ catch ( OperationCanceledException )
285
+ {
286
+ await sourceBuffer . DisposeAsync ( ) ;
287
+ return Stream . Null ;
288
+ }
289
289
290
- if ( buffer . Length == 0 )
291
- {
292
- var errorMessage = process . StandardError . EndOfStream ?
293
- "Empty JSONRPC Response" :
294
- await process . StandardError . ReadToEndAsync ( ) ;
295
- throw new InvalidDataException ( $ "{ context . CurrentPluginMetadata . Name } |{ errorMessage } ") ;
296
- }
290
+ sourceBuffer . Seek ( 0 , SeekOrigin . Begin ) ;
297
291
298
- if ( ! process . StandardError . EndOfStream )
299
- {
300
- using var standardError = process . StandardError ;
301
- var error = await standardError . ReadToEndAsync ( ) ;
292
+ token . ThrowIfCancellationRequested ( ) ;
302
293
303
- if ( ! string . IsNullOrEmpty ( error ) )
304
- {
305
- Log . Error ( $ "| { context . CurrentPluginMetadata . Name } . { nameof ( ExecuteAsync ) } | { error } " ) ;
306
- }
307
- }
294
+ if ( sourceBuffer . Length == 0 )
295
+ {
296
+ var errorMessage = errorBuffer . Length == 0 ?
297
+ "Empty JSONRPC Response" :
298
+ await process . StandardError . ReadToEndAsync ( ) ;
308
299
309
- return buffer ;
300
+ Log . Error ( $ " { context . CurrentPluginMetadata . Name } | { errorMessage } " ) ;
310
301
}
311
- finally
302
+
303
+ if ( errorBuffer . Length != 0 )
312
304
{
313
- exitTokenSource . Cancel ( ) ;
314
- process ? . Dispose ( ) ;
305
+ using var error = new StreamReader ( errorBuffer ) ;
306
+
307
+ var errorMessage = await error . ReadToEndAsync ( ) ;
308
+
309
+ if ( ! string . IsNullOrEmpty ( errorMessage ) )
310
+ {
311
+ Log . Error ( $ "|{ context . CurrentPluginMetadata . Name } .{ nameof ( ExecuteAsync ) } |{ errorMessage } ") ;
312
+ }
315
313
}
314
+
315
+ return sourceBuffer ;
316
316
}
317
317
318
+
318
319
public async Task < List < Result > > QueryAsync ( Query query , CancellationToken token )
319
320
{
320
321
var request = new JsonRPCRequestModel
@@ -366,6 +367,7 @@ public virtual async Task InitAsync(PluginInitContext context)
366
367
private static readonly Thickness settingPanelMargin = new ( 15 , 20 , 15 , 20 ) ;
367
368
private static readonly Thickness settingTextBlockMargin = new ( 10 , 4 , 10 , 4 ) ;
368
369
private JsonRpcConfigurationModel _settingsTemplate ;
370
+
369
371
public Control CreateSettingPanel ( )
370
372
{
371
373
if ( Settings == null )
@@ -397,84 +399,84 @@ public Control CreateSettingPanel()
397
399
switch ( type )
398
400
{
399
401
case "textBlock" :
402
+ {
403
+ contentControl = new TextBlock
400
404
{
401
- contentControl = new TextBlock
402
- {
403
- Text = attribute . Description . Replace ( "\\ r\\ n" , "\r \n " ) ,
404
- Margin = settingTextBlockMargin ,
405
- MaxWidth = 500 ,
406
- TextWrapping = TextWrapping . WrapWithOverflow
407
- } ;
408
- break ;
409
- }
405
+ Text = attribute . Description . Replace ( "\\ r\\ n" , "\r \n " ) ,
406
+ Margin = settingTextBlockMargin ,
407
+ MaxWidth = 500 ,
408
+ TextWrapping = TextWrapping . WrapWithOverflow
409
+ } ;
410
+ break ;
411
+ }
410
412
case "input" :
413
+ {
414
+ var textBox = new TextBox ( )
411
415
{
412
- var textBox = new TextBox ( )
413
- {
414
- Width = 300 ,
415
- Text = Settings [ attribute . Name ] as string ?? string . Empty ,
416
- Margin = settingControlMargin ,
417
- ToolTip = attribute . Description
418
- } ;
419
- textBox . TextChanged += ( _ , _ ) =>
420
- {
421
- Settings [ attribute . Name ] = textBox . Text ;
422
- } ;
423
- contentControl = textBox ;
424
- break ;
425
- }
416
+ Width = 300 ,
417
+ Text = Settings [ attribute . Name ] as string ?? string . Empty ,
418
+ Margin = settingControlMargin ,
419
+ ToolTip = attribute . Description
420
+ } ;
421
+ textBox . TextChanged += ( _ , _ ) =>
422
+ {
423
+ Settings [ attribute . Name ] = textBox . Text ;
424
+ } ;
425
+ contentControl = textBox ;
426
+ break ;
427
+ }
426
428
case "textarea" :
429
+ {
430
+ var textBox = new TextBox ( )
427
431
{
428
- var textBox = new TextBox ( )
429
- {
430
- Width = 300 ,
431
- Height = 120 ,
432
- Margin = settingControlMargin ,
433
- TextWrapping = TextWrapping . WrapWithOverflow ,
434
- AcceptsReturn = true ,
435
- Text = Settings [ attribute . Name ] as string ?? string . Empty ,
436
- ToolTip = attribute . Description
437
- } ;
438
- textBox . TextChanged += ( sender , _ ) =>
439
- {
440
- Settings [ attribute . Name ] = ( ( TextBox ) sender ) . Text ;
441
- } ;
442
- contentControl = textBox ;
443
- break ;
444
- }
432
+ Width = 300 ,
433
+ Height = 120 ,
434
+ Margin = settingControlMargin ,
435
+ TextWrapping = TextWrapping . WrapWithOverflow ,
436
+ AcceptsReturn = true ,
437
+ Text = Settings [ attribute . Name ] as string ?? string . Empty ,
438
+ ToolTip = attribute . Description
439
+ } ;
440
+ textBox . TextChanged += ( sender , _ ) =>
441
+ {
442
+ Settings [ attribute . Name ] = ( ( TextBox ) sender ) . Text ;
443
+ } ;
444
+ contentControl = textBox ;
445
+ break ;
446
+ }
445
447
case "passwordBox" :
448
+ {
449
+ var passwordBox = new PasswordBox ( )
446
450
{
447
- var passwordBox = new PasswordBox ( )
448
- {
449
- Width = 300 ,
450
- Margin = settingControlMargin ,
451
- Password = Settings [ attribute . Name ] as string ?? string . Empty ,
452
- PasswordChar = attribute . passwordChar == default ? '*' : attribute . passwordChar ,
453
- ToolTip = attribute . Description
454
- } ;
455
- passwordBox . PasswordChanged += ( sender , _ ) =>
456
- {
457
- Settings [ attribute . Name ] = ( ( PasswordBox ) sender ) . Password ;
458
- } ;
459
- contentControl = passwordBox ;
460
- break ;
461
- }
451
+ Width = 300 ,
452
+ Margin = settingControlMargin ,
453
+ Password = Settings [ attribute . Name ] as string ?? string . Empty ,
454
+ PasswordChar = attribute . passwordChar == default ? '*' : attribute . passwordChar ,
455
+ ToolTip = attribute . Description
456
+ } ;
457
+ passwordBox . PasswordChanged += ( sender , _ ) =>
458
+ {
459
+ Settings [ attribute . Name ] = ( ( PasswordBox ) sender ) . Password ;
460
+ } ;
461
+ contentControl = passwordBox ;
462
+ break ;
463
+ }
462
464
case "dropdown" :
465
+ {
466
+ var comboBox = new ComboBox ( )
463
467
{
464
- var comboBox = new ComboBox ( )
465
- {
466
- ItemsSource = attribute . Options ,
467
- SelectedItem = Settings [ attribute . Name ] ,
468
- Margin = settingControlMargin ,
469
- ToolTip = attribute . Description
470
- } ;
471
- comboBox . SelectionChanged += ( sender , _ ) =>
472
- {
473
- Settings [ attribute . Name ] = ( string ) ( ( ComboBox ) sender ) . SelectedItem ;
474
- } ;
475
- contentControl = comboBox ;
476
- break ;
477
- }
468
+ ItemsSource = attribute . Options ,
469
+ SelectedItem = Settings [ attribute . Name ] ,
470
+ Margin = settingControlMargin ,
471
+ ToolTip = attribute . Description
472
+ } ;
473
+ comboBox . SelectionChanged += ( sender , _ ) =>
474
+ {
475
+ Settings [ attribute . Name ] = ( string ) ( ( ComboBox ) sender ) . SelectedItem ;
476
+ } ;
477
+ contentControl = comboBox ;
478
+ break ;
479
+ }
478
480
case "checkbox" :
479
481
var checkBox = new CheckBox
480
482
{
@@ -499,6 +501,7 @@ public Control CreateSettingPanel()
499
501
}
500
502
return settingWindow ;
501
503
}
504
+
502
505
public void Save ( )
503
506
{
504
507
if ( Settings != null )
@@ -541,4 +544,5 @@ public void UpdateSettings(Dictionary<string, object> settings)
541
544
}
542
545
}
543
546
}
547
+
544
548
}
0 commit comments