예제 #1
0
        // <summary>
        // Starts the child process and returns the diagnostics client once the child proc connects to the reversed diagnostics pipe.
        // The callee needs to resume the diagnostics client at appropriate time.
        // </summary>
        public static DiagnosticsClient Build(ProcessLauncher childProcLauncher, string toolName, int timeoutInSec)
        {
            if (!childProcLauncher.HasChildProc)
            {
                throw new InvalidOperationException("Must have a valid child process to launch.");
            }
            // Create and start the reversed server
            string diagnosticTransportName   = GetTransportName(toolName);
            ReversedDiagnosticsServer server = new ReversedDiagnosticsServer(diagnosticTransportName);

            server.Start();

            // Start the child proc
            if (!childProcLauncher.Start(diagnosticTransportName))
            {
                throw new InvalidOperationException("Failed to start dotnet-counters.");
            }

            // Wait for attach
            IpcEndpointInfo endpointInfo = server.Accept(TimeSpan.FromSeconds(timeoutInSec));

            // If for some reason a different process attached to us, wait until the expected process attaches.
            while (endpointInfo.ProcessId != childProcLauncher.ChildProc.Id)
            {
                endpointInfo = server.Accept(TimeSpan.FromSeconds(timeoutInSec));
            }
            return(new DiagnosticsClient(endpointInfo.Endpoint));
        }
        public async Task <DiagnosticsClientHolder> Build(CancellationToken ct, int processId, string portName, bool showChildIO, bool printLaunchCommand)
        {
            if (ProcessLauncher.Launcher.HasChildProc)
            {
                // Create and start the reversed server
                string diagnosticTransportName   = GetTransportName(_toolName);
                ReversedDiagnosticsServer server = new ReversedDiagnosticsServer(diagnosticTransportName);
                server.Start();

                // Start the child proc
                if (!ProcessLauncher.Launcher.Start(diagnosticTransportName, ct, showChildIO, printLaunchCommand))
                {
                    throw new InvalidOperationException($"Failed to start '{ProcessLauncher.Launcher.ChildProc.StartInfo.FileName} {ProcessLauncher.Launcher.ChildProc.StartInfo.Arguments}'.");
                }
                IpcEndpointInfo endpointInfo;
                try
                {
                    // Wait for attach
                    endpointInfo = server.Accept(TimeSpan.FromSeconds(_timeoutInSec));

                    // If for some reason a different process attached to us, wait until the expected process attaches.
                    while (endpointInfo.ProcessId != ProcessLauncher.Launcher.ChildProc.Id)
                    {
                        endpointInfo = server.Accept(TimeSpan.FromSeconds(_timeoutInSec));
                    }
                }
                catch (TimeoutException)
                {
                    Console.Error.WriteLine("Unable to start tracing session - the target app failed to connect to the diagnostics port. This may happen if the target application is running .NET Core 3.1 or older versions. Attaching at startup is only available from .NET 5.0 or later.");
                    throw;
                }
                return(new DiagnosticsClientHolder(new DiagnosticsClient(endpointInfo.Endpoint), endpointInfo, server));
            }
            else if (!string.IsNullOrEmpty(portName))
            {
                ReversedDiagnosticsServer server = new ReversedDiagnosticsServer(portName);
                server.Start();
                string fullPort = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? portName : Path.GetFullPath(portName);
                Console.WriteLine($"Waiting for connection on {fullPort}");
                Console.WriteLine($"Start an application with the following environment variable: DOTNET_DiagnosticPorts={fullPort}");

                IpcEndpointInfo endpointInfo = await server.AcceptAsync(ct);

                return(new DiagnosticsClientHolder(new DiagnosticsClient(endpointInfo.Endpoint), endpointInfo, fullPort, server));
            }
            else
            {
                return(new DiagnosticsClientHolder(new DiagnosticsClient(processId)));
            }
        }