Exemplo n.º 1
0
        public async Task <ResultStatus> TryExecuteRemote(Command command, BuilderContext builderContext, IExecuteContext executeContext, LocalCommandContext commandContext)
        {
            while (!CanSpawnParallelProcess())
            {
                await Task.Delay(1, command.CancellationToken);
            }

            var address   = "Stride/CompilerApp/PackageBuilderApp/" + Guid.NewGuid();
            var arguments = $"--slave=\"{address}\" --build-path=\"{builderOptions.BuildDirectory}\"";

            using (var debugger = VisualStudioDebugger.GetAttached())
            {
                if (debugger != null)
                {
                    arguments += $" --reattach-debugger={debugger.ProcessId}";
                }
            }

            // Start ServiceWire pipe for communication with process
            var processBuilderRemote = new ProcessBuilderRemote(assemblyContainer, commandContext, command);
            var host = new NpHost(address, null, null, new StrideServiceWireSerializer());

            host.AddService <IProcessBuilderRemote>(processBuilderRemote);

            var startInfo = new ProcessStartInfo
            {
                // Note: try to get exec server if it exists, otherwise use CompilerApp.exe
                FileName               = LoaderToolLocator.GetExecutable(typeof(PackageBuilder).Assembly.Location),
                Arguments              = arguments,
                WorkingDirectory       = Environment.CurrentDirectory,
                CreateNoWindow         = true,
                UseShellExecute        = false,
                RedirectStandardOutput = true,
                RedirectStandardError  = true,
            };

            host.Open();

            var output = new List <string>();

            var process = new Process {
                StartInfo = startInfo
            };

            process.Start();
            process.OutputDataReceived += (_, args) => LockProcessAndAddDataToList(process, output, args);
            process.ErrorDataReceived  += (_, args) => LockProcessAndAddDataToList(process, output, args);
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            // Note: we don't want the thread to schedule another job since the CPU core will be in use by the process, so we do a blocking WaitForExit.
            process.WaitForExit();

            host.Close();

            NotifyParallelProcessEnded();

            if (process.ExitCode != 0)
            {
                executeContext.Logger.Error($"Remote command crashed with output:{Environment.NewLine}{string.Join(Environment.NewLine, output)}");
            }

            if (processBuilderRemote.Result != null)
            {
                // Register results back locally
                foreach (var outputObject in processBuilderRemote.Result.OutputObjects)
                {
                    commandContext.RegisterOutput(outputObject.Key, outputObject.Value);
                }

                // Register log messages
                foreach (var logMessage in processBuilderRemote.Result.LogMessages)
                {
                    commandContext.Logger.Log(logMessage);
                }

                // Register tags
                foreach (var tag in processBuilderRemote.Result.TagSymbols)
                {
                    commandContext.AddTag(tag.Key, tag.Value);
                }
            }

            return(command.CancellationToken.IsCancellationRequested ? ResultStatus.Cancelled : (process.ExitCode == 0 ? ResultStatus.Successful : ResultStatus.Failed));
        }
Exemplo n.º 2
0
        public static bool EnsureRouterLaunched(bool attachChildJob = false, bool checkIfPortOpen = true)
        {
            try
            {
                // Try to connect to router
                FileVersionInfo runningRouterVersion = null;
                Process         runningRouterProcess = null;
                foreach (var process in Process.GetProcessesByName("Stride.ConnectionRouter"))
                {
                    try
                    {
                        runningRouterVersion = process.MainModule.FileVersionInfo;
                        runningRouterProcess = process;
                        break;
                    }
                    catch (Exception)
                    {
                    }
                }

                // Make sure to use .exe rather than .dll (.NET Core)
                var defaultRouterAssemblyLocation = LoaderToolLocator.GetExecutable(typeof(Router).Assembly.Location);
                if (defaultRouterAssemblyLocation == null)
                {
                    throw new InvalidOperationException("Could not find Connection Router assembly location");
                }

                // Setup with default locations
                var routerAssemblyLocation = defaultRouterAssemblyLocation;
                var routerAssemblyExe      = Path.GetFileName(routerAssemblyLocation);

                // Try to locate using Stride.ConnectionRouter package
                var logger  = new LoggerResult();
                var package = PackageStore.Instance.FindLocalPackage("Stride.ConnectionRouter", new PackageVersionRange(new PackageVersion(StrideVersion.NuGetVersion)));
                if (package != null)
                {
                    routerAssemblyLocation = package.GetFiles().FirstOrDefault(x => string.Compare(Path.GetFileName(x.Path), routerAssemblyExe, true) == 0)?.FullPath ?? routerAssemblyLocation;
                }

                // If already started, check if found version is same that we wanted to start
                if (runningRouterVersion != null)
                {
                    var routerAssemblyFileVersionInfo = FileVersionInfo.GetVersionInfo(routerAssemblyLocation);

                    // Check that current router is at least as good as the one of latest found Stride
                    if (new PackageVersion(routerAssemblyFileVersionInfo.FileVersion) <= new PackageVersion(runningRouterVersion.FileVersion))
                    {
                        return(true);
                    }
                }

                // Kill previous router process (if any)
                if (runningRouterProcess != null)
                {
                    runningRouterProcess.Kill();
                    runningRouterProcess.WaitForExit();
                }

                // Start new router process
                var spawnedRouterProcess = Process.Start(routerAssemblyLocation);

                // If we are in "developer" mode, attach job so that it gets killed with editor
                if (attachChildJob && spawnedRouterProcess != null)
                {
                    new AttachedChildProcessJob(spawnedRouterProcess);
                }

                if (checkIfPortOpen)
                {
                    using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
                    {
                        // Try during 5 seconds (10 * 500 msec)
                        for (int i = 0; i < 10; ++i)
                        {
                            try
                            {
                                socket.Connect("localhost", RouterClient.DefaultPort);
                            }
                            catch (SocketException)
                            {
                                // Try again in 500 msec
                                Thread.Sleep(500);
                                continue;
                            }
                            break;
                        }
                    }
                }

                return(spawnedRouterProcess != null);
            }
            catch
            {
                return(false);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Gets the current proxy.
        /// </summary>
        /// <returns>StrideCommandsProxy.</returns>
        public static IStrideCommands GetProxy()
        {
            lock (commandProxyLock)
            {
                // New instance?
                bool shouldReload = strideCommands == null || solutionChanged || ShouldReload();
                if (!shouldReload)
                {
                    // TODO: Assemblies changed?
                    //shouldReload = ShouldReload();
                }

                // If new instance or assemblies changed, reload
                if (shouldReload)
                {
                    ClosePipeAndProcess();

                    var address = "Stride/VSPackageCommands/" + Guid.NewGuid();

                    var stridePackageInfo = FindStrideSdkDir(solution).Result;
                    if (stridePackageInfo.LoadedVersion == null)
                    {
                        return(null);
                    }

                    var commandAssembly   = stridePackageInfo.SdkPaths.First(x => Path.GetFileNameWithoutExtension(x) == "Stride.VisualStudio.Commands");
                    var commandExecutable = LoaderToolLocator.GetExecutable(commandAssembly); // .NET Core: .dll => .exe

                    var startInfo = new ProcessStartInfo
                    {
                        // Note: try to get exec server if it exists, otherwise use CompilerApp.exe
                        FileName         = commandExecutable,
                        Arguments        = $"--pipe=\"{address}\"",
                        WorkingDirectory = Environment.CurrentDirectory,
                        UseShellExecute  = false,
                    };

                    var strideCommandsProcess = new Process {
                        StartInfo = startInfo
                    };
                    strideCommandsProcess.Start();

                    strideCommandsProcessJob = new AttachedChildProcessJob(strideCommandsProcess);

                    for (int i = 0; i < 10; ++i)
                    {
                        try
                        {
                            strideCommands = new NpClient <IStrideCommands>(new NpEndPoint(address + "/IStrideCommands"));
                            break;
                        }
                        catch
                        {
                            // Last try, forward exception
                            if (i == 9)
                            {
                                throw;
                            }
                            // Wait until process is ready to accept connections
                            Thread.Sleep(100);
                        }
                    }

                    solutionChanged = false;
                }

                return(strideCommands?.Proxy);
            }
        }