コード例 #1
0
        static async Task <int> MainAsync(string [] args)
        {
            if (args.Length == 0 || args [0] == null)
            {
                System.Console.Error.WriteLine("usage: WORKBOOK_PATH");
                return(1);
            }

            var path = new FilePath(args [0]);

            Uri.TryCreate("file://" + path.FullPath, UriKind.Absolute, out var fileUri);

            if (!ClientSessionUri.TryParse(fileUri.AbsoluteUri, out var uri))
            {
                System.Console.Error.WriteLine("Invalid URI");
                return(1);
            }

            new ConsoleClientApp().Initialize(
                logProvider: new LogProvider(LogLevel.Info, null));

            var session = new ClientSession(uri);

            session.InitializeViewControllers(new ConsoleClientSessionViewControllers());
            await session.InitializeAsync(new ConsoleWorkbookPageHost());

            await session.WorkbookPageViewModel.EvaluateAllAsync();

            return(0);
        }
コード例 #2
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            liveInspectionRadioButton.State = NSCellStateValue.On;

            connectButton.KeyEquivalent = "\r";

            locationTextField.Changed += (sender, e) => {
                if (ClientSessionUri.TryParse(locationTextField?.StringValue, out clientSessionUri))
                {
                    clientSessionUriTextField.StringValue = clientSessionUri.ToString();
                }
                else
                {
                    clientSessionUriTextField.StringValue = "Invalid Location";
                }

                ValidateUserInterface();
            };

            ValidateUserInterface();

            locationTextField.BecomeFirstResponder();
        }
コード例 #3
0
        public async Task <IAgentTicket> RequestAgentTicketAsync(
            ClientSessionUri clientSessionUri,
            IMessageService messageService,
            Action disconnectedHandler,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (processManager == null)
            {
                return(null);
            }

            if (ticketType != null)
            {
                return((IAgentTicket)Activator.CreateInstance(
                           ticketType,
                           processManager,
                           messageService,
                           disconnectedHandler));
            }

            var ticket = new AgentProcessTicket(
                processManager,
                messageService,
                disconnectedHandler);

            await ticket.GetAgentProcessStateAsync(cancellationToken);

            return(ticket);
        }
コード例 #4
0
        public void WithHostAndPort()
        {
            var original = new ClientSessionUri("localhost", 54321);

            original.ShouldBeSameAs(original.WithHostAndPort(null, null));
            original.ShouldBeSameAs(original.WithHostAndPort("localhost", null));
            original.ShouldBeSameAs(original.WithHostAndPort(null, 54321));
            original.ShouldBeSameAs(original.WithHostAndPort("localhost", 54321));

            var modifiedHost = original.WithHostAndPort("127.0.0.1", null);

            original.ShouldNotEqual(modifiedHost);
            modifiedHost.Host.ShouldEqual("127.0.0.1");
            modifiedHost.Port.ShouldEqual(original.Port);
            original.ShouldEqual(modifiedHost.WithHostAndPort(original.Host, null));

            var modifiedPort = original.WithHostAndPort(null, 50000);

            original.ShouldNotEqual(modifiedPort);
            modifiedPort.Host.ShouldEqual(original.Host);
            modifiedPort.Port.ShouldEqual((ushort)50000);
            original.ShouldEqual(modifiedPort.WithHostAndPort(null, original.Port));


            var modifiedBoth = original.WithHostAndPort("127.0.0.1", 50000);

            original.ShouldNotEqual(modifiedBoth);
            modifiedBoth.Host.ShouldEqual("127.0.0.1");
            modifiedBoth.Port.ShouldEqual((ushort)50000);
            original.ShouldEqual(modifiedBoth.WithHostAndPort(original.Host, original.Port));
        }
コード例 #5
0
        public AgentProcessTicket(
            IAgentProcessManager agentProcessManager,
            ClientSessionUri clientSessionUri,
            IMessageService messageService,
            Action disconnectedHandler)
        {
            if (agentProcessManager == null)
            {
                throw new ArgumentNullException(nameof(agentProcessManager));
            }

            if (clientSessionUri == null)
            {
                throw new ArgumentNullException(nameof(clientSessionUri));
            }

            if (disconnectedHandler == null)
            {
                throw new ArgumentNullException(nameof(disconnectedHandler));
            }

            AgentProcessManager = agentProcessManager;
            ClientSessionUri    = clientSessionUri;
            MessageService      = messageService;

            this.disconnectedHandler = disconnectedHandler;

            Id = Interlocked.Increment(ref lastId);
        }
コード例 #6
0
 public static void ShouldNotEqual(this ClientSessionUri a, ClientSessionUri b)
 {
     ((object)a).ShouldNotEqual(b);
     ((object)new ClientSessionUri(new Uri(a.ToString())))
     .ShouldNotEqual(new ClientSessionUri(new Uri(b.ToString())));
     (a == b).ShouldBeFalse();
     (a != b).ShouldBeTrue();
 }
コード例 #7
0
        public static void LaunchClientAppForDebugging(Agent agent)
        {
#if DEBUG
            if (!Debugger.IsAttached)
            {
                return;
            }

            var clientAssemblyLocation = Assembly.GetExecutingAssembly().Location;

            var agentType = agent.ClientSessionUri.AgentType;

            InteractiveInstallation.InitializeDefault(null);

            var clientPath = InteractiveInstallation
                             .Default
                             .LocateClientApplication(agent.ClientSessionUri.SessionKind);

            if (string.IsNullOrEmpty(clientPath))
            {
                return;
            }

            var connectUri = new ClientSessionUri(
                agent.Identity.AgentType,
                agent.ClientSessionUri.SessionKind,
                agent.Identity.Host,
                agent.Identity.Port);

            if (HostEnvironment.OS == HostOS.macOS)
            {
                var executableName = Directory.GetFiles(
                    Path.Combine(clientPath, "Contents", "MacOS")) [0];
                clientPath = Path.Combine(clientPath, "Contents", "MacOS", executableName);
            }

            Exec.Log += (sender, e) => {
                if (e.ExitCode == null)
                {
                    Log.Debug(TAG, $"Exec[{e.ExecId}] ({e.Flags}): {e.Arguments}");
                }
                else
                {
                    Log.Debug(TAG, $"Exec[{e.ExecId}] exited: {e.ExitCode}");
                }
            };

            Exec.RunAsync(
                segment => Debug.WriteLine($"!! {segment.Data.TrimEnd ()}"),
                clientPath,
                connectUri).ContinueWith(task => {
                if (task.Exception != null)
                {
                    Log.Error(TAG, task.Exception);
                }
            });
#endif
        }
コード例 #8
0
ファイル: Entry.cs プロジェクト: HankiDesign/workbooks
        /// <summary>
        /// Provides very basic workbook parsing and shunting of code cells
        /// into the evaluation service. Does not display non-code-cell contents
        /// but does evaluate a workbook from top-to-bottom. Restores nuget
        /// packages from the workbook's manifest.
        /// </summary>
        static async Task <int> WorkbookPlayerMain(InteractiveSession session, ClientSessionUri sessionUri)
        {
            var path = new FilePath(sessionUri.WorkbookPath);

            if (!path.FileExists)
            {
                Error.WriteLine($"File does not exist: {path}");
                return(1);
            }

            // load the workbook file
            var workbook = new WorkbookPackage(path);
            await workbook.Open(
                quarantineInfo => Task.FromResult(true),
                path);

            #pragma warning disable 0618
            // TODO: WorkbookDocumentManifest needs to eliminate AgentType like we've done on web
            // to avoid having to use the the flavor mapping in AgentIdentity.
            var targetPlatformIdentifier = AgentIdentity.GetFlavorId(workbook.PlatformTargets [0]);
            #pragma warning restore 0618

            // initialize the session based on manifest metadata from the workbook file
            language = workbook.GetLanguageDescriptions().First();
            await session.InitializeAsync(new InteractiveSessionDescription (
                                              language,
                                              targetPlatformIdentifier,
                                              new EvaluationEnvironment(Environment.CurrentDirectory)));

            // restore NuGet packages
            await session.PackageManagerService.RestoreAsync(
                workbook.Pages.SelectMany(page => page.Packages));

            // insert and evaluate cells in the workbook
            foreach (var cell in workbook.IndexPage.Contents.OfType <CodeCell> ())
            {
                var buffer = cell.CodeAnalysisBuffer.Value;

                lastCodeCellId = await session.EvaluationService.InsertCodeCellAsync(
                    buffer,
                    lastCodeCellId);

                ForegroundColor = ConsoleColor.DarkYellow;
                Write(GetPrompt());
                ResetColor();

                WriteLine(buffer);

                await session.EvaluationService.EvaluateAsync(lastCodeCellId);

                if (lastCellEvaluationStatus != CodeCellEvaluationStatus.Success)
                {
                    break;
                }
            }

            return(0);
        }
コード例 #9
0
        public void OpenWorkbook(string path)
        {
            var systemUri = new Uri(path);
            var uri       = new ClientSessionUri(systemUri);

            uri.WorkbookPath.ShouldEqual(systemUri.LocalPath);
            uri.SessionKind.ShouldEqual(ClientSessionKind.Workbook);
            uri.ToString().ShouldEqual(systemUri.ToString());
        }
コード例 #10
0
        void Open(ClientSessionUri uri)
        {
            var sessionKind = liveInspectionRadioButton.State == NSCellStateValue.On
                ? ClientSessionKind.LiveInspection
                : ClientSessionKind.Workbook;

            if (NSWorkspace.SharedWorkspace.OpenUrl(new NSUrl(uri.WithSessionKind(sessionKind))))
            {
                View.Window.Close();
            }
        }
コード例 #11
0
        public void Schemes()
        {
            Assert.Throws <ArgumentException> (
                () => new ClientSessionUri(new Uri("http://foo")));
            Assert.Throws <ArgumentException> (
                () => new ClientSessionUri(new Uri("relative path", UriKind.Relative)));

            Assert.DoesNotThrow(() => new ClientSessionUri(new Uri("file://foo")));
            Assert.DoesNotThrow(() => new ClientSessionUri(new Uri("C:\\file")));
            Assert.DoesNotThrow(() => CSU("localhost:54321"));

            ClientSessionUri.IsSchemeSupported("xamarin-interactive").ShouldBeTrue();
            ClientSessionUri.IsSchemeSupported("file").ShouldBeTrue();
            ClientSessionUri.IsSchemeSupported("gopher").ShouldBeFalse();
        }
コード例 #12
0
        public void WorkingDirectory()
        {
            const string uriString = "bacon:60000/v1?workingDirectory=/a/b/c";

            var referenceUri = new ClientSessionUri(
                AgentType.Unknown,
                ClientSessionKind.Unknown,
                "bacon",
                60000,
                workingDirectory: "/a/b/c");

            CSU(uriString).ShouldEqual(referenceUri);

            CSU(uriString)
            .WithWorkingDirectory("overwritten")
            .ShouldEqual(referenceUri.WithWorkingDirectory("overwritten"));
        }
コード例 #13
0
        public Agent Start(AgentStartOptions startOptions = null)
        {
            agentServer.Start();
            Identity = Identity
                       .WithHost(agentServer.BaseUri.Host)
                       .WithPort((ushort)agentServer.BaseUri.Port);

            // Default to LiveInspection, and correct later if wrong.
            // Only inspection extensions respond to InspectorSupport.AgentStarted.
            ClientSessionUri = new ClientSessionUri(
                Identity.AgentType,
                startOptions?.ClientSessionKind ?? ClientSessionKind.LiveInspection,
                Identity.Host,
                Identity.Port);

            startOptions?.AgentStarted?.Invoke(ClientSessionUri);

            try {
                var identifyAgentRequest = GetIdentifyAgentRequest();

                if (identifyAgentRequest != null)
                {
                    ClientSessionUri = ClientSessionUri.WithSessionKind(ClientSessionKind.Workbook);
                    WriteAgentIdentityAsync(identifyAgentRequest).ContinueWithOnMainThread(task => {
                        if (task.IsFaulted)
                        {
                            Log.Error(
                                TAG,
                                $"{nameof (WriteAgentIdentityAsync)}",
                                task.Exception);
                            IdentificationFailure?.Invoke(this, EventArgs.Empty);
                        }
                    });
                }
            } catch (Exception e) {
                Log.Error(TAG, e);
                IdentificationFailure?.Invoke(this, EventArgs.Empty);
            }

            Log.Info(TAG, $"{Identity.AgentType} '{Identity.ApplicationName}' "
                     + $"is available for interaction: {ClientSessionUri}");

            return(this);
        }
コード例 #14
0
        public void WithParameters()
        {
            var original = new ClientSessionUri(AgentType.iOS, ClientSessionKind.Workbook);

            original.ShouldBeSameAs(original.WithParameters(null));
            original.ShouldBeSameAs(original.WithParameters(Array.Empty <KeyValuePair <string, string> > ()));

            var parameters = new [] {
                new KeyValuePair <string, string> ("feature", "xamarin.forms"),
                new KeyValuePair <string, string> ("random thing", "blah & blah")
            };

            var modified = original.WithParameters(parameters);

            modified.Parameters.Length.ShouldEqual(2);
            modified.Parameters.SequenceShouldEqual(parameters);

            var fromSystemUri = CSU("/v1?sessionKind=Workbook&agentType=iOS&feature=xamarin.forms&random%20thing=blah%20%26%20blah");

            fromSystemUri.ShouldEqual(modified);
        }
コード例 #15
0
        public static AgentSessionWindow Open(ClientSessionUri clientSessionUri)
        {
            AgentSessionWindow window;

            if (!SessionController.TryGetApplicationState(clientSessionUri, out window))
            {
                window = new AgentSessionWindow(clientSessionUri);
            }

            window.Show();
            window.Activate();

            // Sometimes (like when clicking the Inspect button in VS), Activate fails to
            // bring the client window to the foreground (very obvious if it is behind VS).
            // This hack temporarily sets the window to be always-on-top to force it to
            // the foreground, then immediately unsets that property.
            window.Topmost = true;
            window.Topmost = false;

            return(window);
        }
コード例 #16
0
        AgentSessionWindow(ClientSessionUri clientSessionUri)
        {
            MessageViewDelegate       = new WpfMessageViewDelegate(this);
            DialogMessageViewDelegate = new WpfDialogMessageViewDelegate(this);

            Session = new ClientSession(clientSessionUri);
            Session.InitializeViewControllers(
                new WpfClientSessionViewControllers(MessageViewDelegate, DialogMessageViewDelegate));

            SessionController.AddSession(Session, this);

            InitializeComponent();
            DataContext = this;
            ViewModel   = new ViewInspectorViewModel <AgentSessionWindow> (Session, this);
            menuManager = new MenuManager(mainMenu, this, Session.SessionKind != ClientSessionKind.LiveInspection);

            replWebView.Loaded        += HandleWebViewControlLoaded;
            replWebView.LoadCompleted += HandleWebViewSourceLoadCompleted;

            propertyEditor.EditorProvider = new InteractiveEditorProvider(Session, new WpfPropertyViewHelper());
        }
コード例 #17
0
        public void TryParse(
            string uriString,
            bool expectedResult,
            string host,
            int port,
            ClientSessionKind clientSessionKind)
        {
            ClientSessionUri uri;

            ClientSessionUri.TryParse(uriString, out uri).ShouldEqual(expectedResult);

            if (!expectedResult)
            {
                return;
            }

            uri.Host.ShouldEqual(host);
            uri.Port.ShouldEqual((ushort)port);
            uri.SessionKind.ShouldEqual(clientSessionKind);

            Assert.DoesNotThrow(() => uri.ToString());
        }
コード例 #18
0
        public void WithAssemblySearchPaths()
        {
            var original = new ClientSessionUri(AgentType.iOS, ClientSessionKind.LiveInspection);

            original.ShouldBeSameAs(original.WithAssemblySearchPaths(null));
            original.ShouldBeSameAs(original.WithAssemblySearchPaths(new string [0]));

            var modified = original.WithAssemblySearchPaths(new [] { "hello" });

            modified.AssemblySearchPaths.Length.ShouldEqual(1);
            modified.AssemblySearchPaths [0].ShouldEqual("hello");

            original = new ClientSessionUri("localhost", 54321, new [] { "a", "b", "c" });
            original.ShouldBeSameAs(original.WithAssemblySearchPaths(new [] { "a", "b", "c" }));
            original.WithAssemblySearchPaths(null).AssemblySearchPaths.Length.ShouldEqual(0);
            original.WithAssemblySearchPaths(new string [0]).AssemblySearchPaths.Length.ShouldEqual(0);

            modified = original.WithAssemblySearchPaths(new [] { "x", "y" });
            modified.AssemblySearchPaths.Length.ShouldEqual(2);
            modified.AssemblySearchPaths [0].ShouldEqual("x");
            modified.AssemblySearchPaths [1].ShouldEqual("y");
        }
コード例 #19
0
 internal static InteractiveSession CreateLiveInspectionSession(
     ClientSessionUri liveInspectAgentUri)
 => new InteractiveSession(
コード例 #20
0
 public SessionDocument OpenDocument(ClientSessionUri uri)
 => OpenDocument(new NSUrl(uri));
コード例 #21
0
ファイル: Entry.cs プロジェクト: HankiDesign/workbooks
        static async Task <int> MainAsync(string [] args)
        {
            ClientSessionUri sessionUri = null;
            TextWriter       logWriter  = null;
            var showHelp = false;

            var options = new OptionSet {
                { "usage: xic [OPTIONS]+ [URI]" },
                { "" },
                { "Options:" },
                { "" },
                { "l|log=", "Write debugging log to file",
                  v => logWriter = new StreamWriter(v) },
                { "h|help", "Show this help",
                  v => showHelp = true }
            };

            try {
                args = options.Parse(args).ToArray();
            } catch (Exception e) {
                Error.WriteLine($"Invalid option: {e.Message}");
                showHelp = true;
            }

            if (showHelp)
            {
                options.WriteOptionDescriptions(Out);
                return(1);
            }

            if (args.Length > 0)
            {
                if (!ClientSessionUri.TryParse(args [0], out sessionUri))
                {
                    Error.WriteLine($"Invalid URI: {args [0]}");
                    return(1);
                }
            }

            // set up the very basic global services/environment
            var clientApp = new ConsoleClientApp();

            clientApp.Initialize(
                logProvider: new LogProvider(LogLevel.Info, logWriter));

            // Now create and get ready to deal with the session; a more complete
            // client should handle more than just OnNext from the observer.
            var session = new InteractiveSession(agentUri: sessionUri);

            session.Events.Subscribe(new Observer <InteractiveSessionEvent> (OnSessionEvent));

            if (sessionUri?.WorkbookPath != null)
            {
                await WorkbookPlayerMain(session, sessionUri);
            }
            else
            {
                await ReplPlayerMain(session);
            }

            // Nevermind this... it'll get fixed!
            await Task.Delay(Timeout.Infinite);

            return(0);
        }
コード例 #22
0
ファイル: Driver.cs プロジェクト: pietervp/workbooks-1
        public int Run()
        {
            var workbooksApp = Path.Combine(
                Environment.CurrentDirectory,
                InteractiveInstallation.Default.LocateClientApplication(
                    ClientSessionKind.Workbook));

            var launchUris = new List <ClientSessionUri> ();

            foreach (var uriString in ClientLaunchUris)
            {
                ClientSessionUri uri = null;

                if (File.Exists(uriString) || Directory.Exists(uriString))
                {
                    try {
                        var fileUri = new Uri(
                            Path.Combine(Environment.CurrentDirectory, uriString));
                        uri = new ClientSessionUri(fileUri);
                    } catch {
                    }
                }

                if (uri == null && !ClientSessionUri.TryParse(uriString, out uri))
                {
                    AgentType agentType;

                    if (String.Equals(uriString, "mac", StringComparison.OrdinalIgnoreCase))
                    {
                        agentType = AgentType.MacNet45;
                    }
                    else if (!Enum.TryParse(uriString, true, out agentType))
                    {
                        throw new Exception($"Invalid URI or platform '{uriString}'");
                    }

                    uri = new ClientSessionUri(agentType, ClientSessionKind.Workbook);
                }

                launchUris.Add(uri);
            }

            if (launchUris.Count == 0)
            {
                launchUris.Add(new ClientSessionUri(AgentType.Console, ClientSessionKind.Workbook));
            }

            var workingDirectory = Environment.CurrentDirectory;

            var arguments = new List <string> ();

            foreach (var launchUri in launchUris)
            {
                var uri = launchUri;
                if (uri.WorkbookPath == null)
                {
                    uri = uri.WithWorkingDirectory(workingDirectory);
                }

                arguments.Add($"\"{uri}\"");
            }

            if (InteractiveInstallation.Default.IsMac)
            {
                arguments.Insert(0, $"\"{workbooksApp}\"");
                arguments.Insert(0, "-a");
                Exec("open", arguments);
            }
            else
            {
                Exec(workbooksApp, arguments);
            }

            return(0);
        }
コード例 #23
0
ファイル: Driver.cs プロジェクト: vnvizitiu/workbooks
        public int Run()
        {
            var    isMac = Environment.OSVersion.Platform == PlatformID.Unix;
            string workbooksApp;

            var driverLocation = Assembly.GetExecutingAssembly().Location;

            if (isMac)
            {
                workbooksApp = new FilePath(Path.GetDirectoryName(driverLocation)).Combine(
                    "..",
                    "..").FullPath;
            }
            else
            {
                workbooksApp = Assembly.GetExecutingAssembly().Location;
            }

            var launchUris = new List <ClientSessionUri> ();

            foreach (var uriString in ClientLaunchUris)
            {
                ClientSessionUri uri = null;

                if (File.Exists(uriString) || Directory.Exists(uriString))
                {
                    try {
                        var fileUri = new Uri(
                            Path.Combine(Environment.CurrentDirectory, uriString));
                        uri = new ClientSessionUri(fileUri);
                    } catch {
                    }
                }

                if (uri == null && !ClientSessionUri.TryParse(uriString, out uri))
                {
                    AgentType agentType;

                    if (String.Equals(uriString, "mac", StringComparison.OrdinalIgnoreCase))
                    {
                        agentType = AgentType.MacNet45;
                    }
                    else if (!Enum.TryParse(uriString, true, out agentType))
                    {
                        throw new Exception($"Invalid URI or platform '{uriString}'");
                    }

                    uri = new ClientSessionUri(agentType, ClientSessionKind.Workbook);
                }

                launchUris.Add(uri);
            }

            if (launchUris.Count == 0)
            {
                launchUris.Add(new ClientSessionUri(AgentType.Console, ClientSessionKind.Workbook));
            }

            var workingDirectory = Environment.CurrentDirectory;

            var arguments = new List <string> ();

            foreach (var launchUri in launchUris)
            {
                var uri = launchUri;
                if (uri.WorkbookPath == null)
                {
                    uri = uri.WithWorkingDirectory(workingDirectory);
                }

                arguments.Add($"\"{uri}\"");
            }

            if (isMac)
            {
                arguments.Insert(0, $"\"{workbooksApp}\"");
                arguments.Insert(0, "-a");
                Exec("open", arguments);
            }
            else
            {
                Exec(workbooksApp, arguments);
            }

            return(0);
        }
コード例 #24
0
        public static void LaunchClientAppForDebugging(Agent agent)
        {
#if DEBUG
            if (!Debugger.IsAttached)
            {
                return;
            }

            var clientAssemblyLocation = Assembly.GetExecutingAssembly().Location;

            var buildDepth = 5;
            var agentType  = agent.ClientSessionUri.AgentType;

            // The Mac executable is more deeply nested, so we need to go up a little further
            // to get the base build path.
            if (agentType == AgentType.MacMobile || agentType == AgentType.MacNet45)
            {
                buildDepth = 7;
            }

            var buildDir = clientAssemblyLocation;
            for (var i = 0; i < buildDepth; i++)
            {
                buildDir = Path.GetDirectoryName(buildDir);
            }

            InteractiveInstallation.InitializeDefault(
                isMac: Environment.OSVersion.Platform == PlatformID.Unix,
                buildPath: buildDir);

            var clientPath = InteractiveInstallation
                             .Default
                             .LocateClientApplication(agent.ClientSessionUri.SessionKind);

            if (string.IsNullOrEmpty(clientPath))
            {
                return;
            }

            var connectUri = new ClientSessionUri(
                agent.Identity.AgentType,
                agent.ClientSessionUri.SessionKind,
                agent.Identity.Host,
                agent.Identity.Port);

            if (InteractiveInstallation.Default.IsMac)
            {
                var executableName = Directory.GetFiles(
                    Path.Combine(clientPath, "Contents", "MacOS")) [0];
                clientPath = Path.Combine(clientPath, "Contents", "MacOS", executableName);
            }

            Exec.Log += (sender, e) => {
                if (e.ExitCode == null)
                {
                    Log.Debug(TAG, $"Exec[{e.ExecId}] ({e.Flags}): {e.Arguments}");
                }
                else
                {
                    Log.Debug(TAG, $"Exec[{e.ExecId}] exited: {e.ExitCode}");
                }
            };

            Exec.RunAsync(
                segment => Debug.WriteLine($"!! {segment.Data.TrimEnd ()}"),
                clientPath,
                connectUri).ContinueWith(task => {
                if (task.Exception != null)
                {
                    Log.Error(TAG, task.Exception);
                }
            });
#endif
        }