Make ShellExec async by implementing process awaiter
MODIFY
WalletWasabi.Gui/Global.cs
WalletWasabi.Gui/Global.cs
@@ -638,7 +638,7 @@ namespace WalletWasabi.Gui
{
message = Guard.Correct(message);
title = Guard.Correct(title);
- NotificationHelpers.Notify(message, title, notificationType, () => FileHelpers.OpenFileInTextEditor(Logger.FilePath));
+ NotificationHelpers.Notify(message, title, notificationType, async () => await FileHelpers.OpenFileInTextEditorAsync(Logger.FilePath));
Logger.LogInfo($"Transaction Notification ({notificationType}): {title} - {message} - {e.Transaction.GetHash()}");
}

MODIFY
WalletWasabi.Gui/Helpers/FileHelpers.cs
WalletWasabi.Gui/Helpers/FileHelpers.cs
@@ -2,6 +2,7 @@ using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
+using System.Threading.Tasks;
using WalletWasabi.Helpers;
using WalletWasabi.Logging;
@@ -9,7 +10,7 @@ namespace WalletWasabi.Gui.Helpers
{
public static class FileHelpers
{
- public static void OpenFileInTextEditor(string filePath)
+ public static async Task OpenFileInTextEditorAsync(string filePath)
{
if (File.Exists(filePath))
{
@@ -17,7 +18,7 @@ namespace WalletWasabi.Gui.Helpers
{
// If no associated application/json MimeType is found xdg-open opens retrun error
// but it tries to open it anyway using the console editor (nano, vim, other..)
- EnvironmentHelpers.ShellExec($"gedit {filePath} || xdg-open {filePath}", waitForExit: false);
+ await EnvironmentHelpers.ShellExecAsync($"gedit {filePath} || xdg-open {filePath}", waitForExit: false);
}
else
{
@@ -37,7 +38,7 @@ namespace WalletWasabi.Gui.Helpers
if (openWithNotepad)
{
// Open file using Notepad.
- using Process process = Process.Start(new ProcessStartInfo
+ using Process notepadProcess = Process.Start(new ProcessStartInfo
{
FileName = "notepad.exe",
Arguments = filePath,
@@ -49,14 +50,13 @@ namespace WalletWasabi.Gui.Helpers
}
// Open file wtih the default editor.
- using (Process process = Process.Start(new ProcessStartInfo
+ using Process defaultEditorProcess = Process.Start(new ProcessStartInfo
{
FileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? filePath : "open",
Arguments = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? $"-e {filePath}" : "",
CreateNoWindow = true,
UseShellExecute = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
- }))
- { }
+ });
}
}
else

MODIFY
WalletWasabi.Gui/Shell/Commands/DiskCommands.cs
WalletWasabi.Gui/Shell/Commands/DiskCommands.cs
@@ -4,6 +4,7 @@ using System;
using System.Composition;
using System.IO;
using System.Reactive.Linq;
+using System.Threading.Tasks;
using WalletWasabi.Gui.Helpers;
using WalletWasabi.Logging;
@@ -68,19 +69,19 @@ namespace WalletWasabi.Gui.Shell.Commands
IoHelpers.OpenFolderInFileExplorer(Global.WalletsDir);
}
- private void OnOpenLogFile()
+ private Task OnOpenLogFile()
{
- FileHelpers.OpenFileInTextEditor(Logger.FilePath);
+ return FileHelpers.OpenFileInTextEditorAsync(Logger.FilePath);
}
- private void OnOpenTorLogFile()
+ private Task OnOpenTorLogFile()
{
- FileHelpers.OpenFileInTextEditor(Global.TorLogsFile);
+ return FileHelpers.OpenFileInTextEditorAsync(Global.TorLogsFile);
}
- private void OnOpenConfigFile()
+ private Task OnOpenConfigFile()
{
- FileHelpers.OpenFileInTextEditor(Global.Config.FilePath);
+ return FileHelpers.OpenFileInTextEditorAsync(Global.Config.FilePath);
}
[ExportCommandDefinition("File.Open.DataFolder")]

MODIFY
WalletWasabi.Gui/Shell/Commands/HelpCommands.cs
WalletWasabi.Gui/Shell/Commands/HelpCommands.cs
@@ -31,11 +31,11 @@ namespace WalletWasabi.Gui.Shell.Commands
CustomerSupportCommand = new CommandDefinition(
"Customer Support",
commandIconService.GetCompletionKindImage("CustomerSupport"),
- ReactiveCommand.Create(() =>
+ ReactiveCommand.CreateFromTask(async () =>
{
try
{
- IoHelpers.OpenBrowser("https://www.reddit.com/r/WasabiWallet/");
+ await IoHelpers.OpenBrowserAsync("https://www.reddit.com/r/WasabiWallet/");
}
catch (Exception ex)
{
@@ -47,11 +47,11 @@ namespace WalletWasabi.Gui.Shell.Commands
ReportBugCommand = new CommandDefinition(
"Report Bug",
commandIconService.GetCompletionKindImage("ReportBug"),
- ReactiveCommand.Create(() =>
+ ReactiveCommand.CreateFromTask(async () =>
{
try
{
- IoHelpers.OpenBrowser("https://github.com/zkSNACKs/WalletWasabi/issues");
+ await IoHelpers.OpenBrowserAsync("https://github.com/zkSNACKs/WalletWasabi/issues");
}
catch (Exception ex)
{
@@ -63,11 +63,11 @@ namespace WalletWasabi.Gui.Shell.Commands
DocsCommand = new CommandDefinition(
"Documentation",
commandIconService.GetCompletionKindImage("Documentation"),
- ReactiveCommand.Create(() =>
+ ReactiveCommand.CreateFromTask(async () =>
{
try
{
- IoHelpers.OpenBrowser("https://docs.wasabiwallet.io/");
+ await IoHelpers.OpenBrowserAsync("https://docs.wasabiwallet.io/");
}
catch (Exception ex)
{

MODIFY
WalletWasabi.Gui/Tabs/AboutViewModel.cs
WalletWasabi.Gui/Tabs/AboutViewModel.cs
@@ -20,7 +20,7 @@ namespace WalletWasabi.Gui.Tabs
public AboutViewModel(Global global) : base(global, "About")
{
- OpenBrowserCommand = ReactiveCommand.Create<string>(x => IoHelpers.OpenBrowser(x));
+ OpenBrowserCommand = ReactiveCommand.Create<string>(async x => await IoHelpers.OpenBrowserAsync(x));
OpenBrowserCommand.ThrownExceptions
.ObserveOn(RxApp.TaskpoolScheduler)

MODIFY
WalletWasabi.Gui/Tabs/SettingsViewModel.cs
WalletWasabi.Gui/Tabs/SettingsViewModel.cs
@@ -19,6 +19,7 @@ using WalletWasabi.Gui.ViewModels.Validation;
using WalletWasabi.Helpers;
using WalletWasabi.Models;
using WalletWasabi.Logging;
+using System.Threading.Tasks;
namespace WalletWasabi.Gui.Tabs
{
@@ -89,7 +90,7 @@ namespace WalletWasabi.Gui.Tabs
.ObserveOn(RxApp.TaskpoolScheduler)
.Subscribe(x => Global.UiConfig.IsCustomFee = x);
- OpenConfigFileCommand = ReactiveCommand.Create(OpenConfigFile);
+ OpenConfigFileCommand = ReactiveCommand.CreateFromTask(OpenConfigFile);
LurkingWifeModeCommand = ReactiveCommand.CreateFromTask(async () =>
{
@@ -392,9 +393,9 @@ namespace WalletWasabi.Gui.Tabs
});
}
- private void OpenConfigFile()
+ private Task OpenConfigFile()
{
- FileHelpers.OpenFileInTextEditor(Global.Config.FilePath);
+ return FileHelpers.OpenFileInTextEditorAsync(Global.Config.FilePath);
}
#region Validation

MODIFY
WalletWasabi.Gui/Tabs/WalletManager/LoadWalletViewModel.cs
WalletWasabi.Gui/Tabs/WalletManager/LoadWalletViewModel.cs
@@ -142,7 +142,7 @@ namespace WalletWasabi.Gui.Tabs.WalletManager
EnumerateHardwareWalletsCommand = ReactiveCommand.CreateFromTask(async () => await EnumerateHardwareWalletsAsync());
- OpenBrowserCommand = ReactiveCommand.Create<string>(x => IoHelpers.OpenBrowser(x));
+ OpenBrowserCommand = ReactiveCommand.Create<string>(async x => await IoHelpers.OpenBrowserAsync(x));
Observable
.Merge(OpenBrowserCommand.ThrownExceptions)

MODIFY
WalletWasabi.Gui/ViewModels/StatusBarViewModel.cs
WalletWasabi.Gui/ViewModels/StatusBarViewModel.cs
@@ -254,11 +254,11 @@ namespace WalletWasabi.Gui.ViewModels
CriticalUpdateAvailable = !x.BackendCompatible;
});
- UpdateCommand = ReactiveCommand.Create(() =>
+ UpdateCommand = ReactiveCommand.CreateFromTask(async () =>
{
try
{
- IoHelpers.OpenBrowser("https://wasabiwallet.io/#download");
+ await IoHelpers.OpenBrowserAsync("https://wasabiwallet.io/#download");
}
catch (Exception ex)
{

MODIFY
WalletWasabi/Extensions/ProcessExtensions.cs
WalletWasabi/Extensions/ProcessExtensions.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -70,5 +71,14 @@ namespace System.Diagnostics
Logger.LogError(ex, nameof(ProcessExtensions));
}
}
+
+ public static TaskAwaiter<int> GetAwaiter(this Process process)
+ {
+ var tcs = new TaskCompletionSource<int>();
+ process.EnableRaisingEvents = true;
+ process.Exited += (s, e) => tcs.TrySetResult(process.ExitCode);
+ if (process.HasExited) tcs.TrySetResult(process.ExitCode);
+ return tcs.Task.GetAwaiter();
+ }
}
}

MODIFY
WalletWasabi/Helpers/EnvironmentHelpers.cs
WalletWasabi/Helpers/EnvironmentHelpers.cs
@@ -5,6 +5,7 @@ using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Threading.Tasks;
using WalletWasabi.Logging;
namespace WalletWasabi.Helpers
@@ -159,12 +160,17 @@ namespace WalletWasabi.Helpers
return fileNameWithoutExtension;
}
+ public static void ShellExec(string cmd, bool waitForExit = true)
+ {
+ ShellExecAsync(cmd, waitForExit).GetAwaiter().GetResult();
+ }
+
/// <summary>
/// Executes a command with bash.
/// https://stackoverflow.com/a/47918132/2061103
/// </summary>
/// <param name="cmd"></param>
- public static void ShellExec(string cmd, bool waitForExit = true)
+ public static async Task ShellExecAsync(string cmd, bool waitForExit = true)
{
var escapedArgs = cmd.Replace("\"", "\\\"");
@@ -181,10 +187,10 @@ namespace WalletWasabi.Helpers
);
if(waitForExit)
{
- process.WaitForExit();
- if (process.ExitCode != 0)
+ var exitCode = await process;
+ if (exitCode != 0)
{
- Logger.LogError($"{nameof(ShellExec)} command: {cmd} exited with exit code: {process.ExitCode}, instead of 0.");
+ Logger.LogError($"{nameof(ShellExecAsync)} command: {cmd} exited with exit code: {exitCode}, instead of 0.");
}
}
}

MODIFY
WalletWasabi/Helpers/IoHelpers.cs
WalletWasabi/Helpers/IoHelpers.cs
@@ -2,9 +2,6 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Compression;
using System.Runtime.InteropServices;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Helpers;
using WalletWasabi.Logging;
@@ -144,13 +141,13 @@ namespace System.IO
}
}
- public static void OpenBrowser(string url)
+ public static async Task OpenBrowserAsync(string url)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
// If no associated application/json MimeType is found xdg-open opens retrun error
// but it tries to open it anyway using the console editor (nano, vim, other..)
- EnvironmentHelpers.ShellExec($"xdg-open {url}", waitForExit: false);
+ await EnvironmentHelpers.ShellExecAsync($"xdg-open {url}", waitForExit: false);
}
else
{

Make ShellExec async by implementing process awaiter