/// <summary>
        /// Attempts to start a new instance of the app with optional program arguments
        /// </summary>
        /// <remarks>
        /// This method is only functional on the published builds
        /// and not on debugging runs.
        /// </remarks>
        /// <param name="args">The program arguments to pass to the new instance.</param>
        public static void StartAppWithArgs(string args = "")
        {
            var path = Process.GetCurrentProcess().MainModule?.FileName;

            if (string.IsNullOrEmpty(path))
            {
                throw new InvalidOperationException($"Invalid path: '{path}'");
            }

            var startInfo = ProcessStartInfoFactory.Make(path, args);

            using var p = Process.Start(startInfo);
        }
    public async Task <(string response, int exitCode)> SendCommandAsync(string arguments, bool openConsole, CancellationToken cancel, Action <StreamWriter>?standardInputWriter = null)
    {
        ProcessStartInfo startInfo = ProcessStartInfoFactory.Make(ProcessPath, arguments, openConsole);

        (string rawResponse, int exitCode) = await SendCommandAsync(startInfo, cancel, standardInputWriter).ConfigureAwait(false);

        string response;

        if (!openConsole)
        {
            response = rawResponse;
        }
        else
        {
            response = exitCode == 0
                                ? "{\"success\":\"true\"}"
                                : $"{{\"success\":\"false\",\"error\":\"Process terminated with exit code: {exitCode}.\"}}";
        }

        return(response, exitCode);
    }
    public static void Invoke(Exception exceptionToReport)
    {
        try
        {
            var serializedException   = exceptionToReport.ToSerializableException();
            var base64ExceptionString = SerializableException.ToBase64String(serializedException);
            var args = $"crashreport -exception=\"{base64ExceptionString}\"";

            var path = Process.GetCurrentProcess().MainModule?.FileName;
            if (string.IsNullOrEmpty(path))
            {
                throw new InvalidOperationException($"Invalid path: '{path}'");
            }

            ProcessStartInfo startInfo = ProcessStartInfoFactory.Make(path, args);
            using Process? p = Process.Start(startInfo);
        }
        catch (Exception ex)
        {
            Logger.LogWarning($"There was a problem while invoking crash report: '{ex}'.");
        }
    }
Beispiel #4
0
        public void TryInvokeCrashReport()
        {
            try
            {
                if (Attempts >= MaxRecursiveCalls)
                {
                    throw new InvalidOperationException($"The crash report has been called {MaxRecursiveCalls} times. Will not continue to avoid recursion errors.");
                }
                if (string.IsNullOrEmpty(Base64ExceptionString))
                {
                    throw new InvalidOperationException($"The crash report exception message is empty.");
                }

                var args = $"crashreport -attempt=\"{Attempts + 1}\" -exception=\"{Base64ExceptionString}\"";

                ProcessStartInfo startInfo = ProcessStartInfoFactory.Make(Process.GetCurrentProcess().MainModule.FileName, args);
                using Process p = Process.Start(startInfo);
            }
            catch (Exception ex)
            {
                Logger.LogWarning($"There was a problem while invoking crash report:{ex.ToUserFriendlyString()}.");
            }
        }
Beispiel #5
0
        /// <summary>
        /// This method can be called only once.
        /// </summary>
        public async Task StartAsync(CancellationToken cancel)
        {
            int    ptcv            = PrintToConsole ? 1 : 0;
            string processPath     = MicroserviceHelpers.GetBinaryPath("bitcoind");
            string networkArgument = NetworkTranslator.GetCommandLineArguments(Network);

            string args = $"{networkArgument} -datadir=\"{DataDir}\" -printtoconsole={ptcv}";

            // Start bitcoind process.
            Process = new ProcessAsync(ProcessStartInfoFactory.Make(processPath, args));
            Process.Start();

            // Store PID in PID file.
            await PidFile.WriteFileAsync(Process.Id).ConfigureAwait(false);

            CachedPid = Process.Id;

            try
            {
                var exceptionTracker = new LastExceptionTracker();

                // Try to connect to bitcoin daemon RPC until we succeed.
                while (true)
                {
                    try
                    {
                        TimeSpan timeSpan = await RpcClient.UptimeAsync(cancel).ConfigureAwait(false);

                        Logger.LogInfo("RPC connection is successfully established.");
                        Logger.LogDebug($"RPC uptime is: {timeSpan}.");

                        // Bitcoin daemon is started. We are done.
                        break;
                    }
                    catch (Exception ex)
                    {
                        ExceptionInfo exceptionInfo = exceptionTracker.Process(ex);

                        // Don't log extensively.
                        if (exceptionInfo.IsFirst)
                        {
                            Logger.LogInfo($"{Constants.BuiltinBitcoinNodeName} is not yet ready... Reason: {exceptionInfo.Exception.Message}");
                        }

                        if (Process is { } p&& p.HasExited)
                        {
                            throw new BitcoindException($"Failed to start daemon, location: '{p.StartInfo.FileName} {p.StartInfo.Arguments}'", ex);
                        }
                    }

                    if (cancel.IsCancellationRequested)
                    {
                        Logger.LogDebug("Bitcoin daemon was not started yet and user requested to cancel the operation.");
                        await StopAsync(onlyOwned : true).ConfigureAwait(false);

                        cancel.ThrowIfCancellationRequested();
                    }

                    // Wait a moment before the next check.
                    await Task.Delay(100, cancel).ConfigureAwait(false);
                }
            }
            catch (Exception)
            {
                Process?.Dispose();
                throw;
            }
        }