public int InstallKernelSpec()

in src/KernelApplication.cs [387:540]


        public int InstallKernelSpec(bool develop,
                                     LogLevel logLevel,
                                     string? prefix = null, IEnumerable<string>? extraInstallArgs = null,
                                     IDictionary<string, Func<Stream>>? additionalFiles = null,
                                     IEnumerable<string>? additionalKernelArguments = null,
                                     string? pathToTool = null,
                                     string? kernelName = null)
        {
            var kernelSpecDir = "";
            KernelSpec kernelSpec;
            if (develop)
            {
                if (pathToTool != null)
                {
                    throw new InvalidDataException("Cannot use development mode together with custom tool paths.");
                }

                System.Console.WriteLine(
                    $"NOTE: Installing a kernel spec which references this directory.\n" +
                    $"      Any changes made in this directory will affect the operation of the {properties.FriendlyName} kernel.\n" +
                    $"      If this was not what you intended, run 'install' without the '--develop' option."
                );

                // Serialize a new kernel spec that points to this directory.
                kernelSpec = new KernelSpec
                {
                    DisplayName = properties.FriendlyName,
                    LanguageName = properties.LanguageName,
                    Arguments = new List<string> {
                        "dotnet", "run",
                        "--project", Directory.GetCurrentDirectory(),
                        "--", "kernel",
                        "--log-level", logLevel.ToString(),
                        "{connection_file}"
                    }
                };
            }
            else
            {
                var kernelArgs = new List<string>();
                if (pathToTool != null)
                {
                    kernelArgs.Add(pathToTool);
                }
                else
                {
                    if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "dotnet")
                    {
                        kernelArgs.AddRange(new[] { "dotnet", properties.KernelName });
                    }
                    else
                    {
                        kernelArgs.Add(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
                    }
                }

                kernelArgs.AddRange(
                    new[]
                    {
                        "kernel",
                        "--log-level", logLevel.ToString(),
                        "{connection_file}"
                    }
                );

                kernelSpec = new KernelSpec
                {
                    DisplayName = properties.FriendlyName,
                    LanguageName = properties.LanguageName,
                    Arguments = kernelArgs
                };
            }

            // Add any additional arguments to the kernel spec as needed.
            if (additionalKernelArguments != null)
            {
                kernelSpec.Arguments.AddRange(additionalKernelArguments);
            }

            // Make a temporary directory to hold the kernel spec.
            var tempKernelSpecDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            var jsonPath = Path.Combine(tempKernelSpecDir, "kernel.json");
            Directory.CreateDirectory(tempKernelSpecDir);
            File.WriteAllText(jsonPath, JsonConvert.SerializeObject(kernelSpec));
            kernelSpecDir = tempKernelSpecDir;

            // Add any additional files we may need.
            if (additionalFiles != null)
            {
                foreach (var (fileName, streamAction) in additionalFiles)
                {
                    var dest = Path.Combine(tempKernelSpecDir, fileName);
                    var sourceStream = streamAction();
                    // Create nested directory
                    Directory.CreateDirectory(Path.GetDirectoryName(dest));
                    using (var destStream = File.OpenWrite(dest))
                    {
                        sourceStream.CopyTo(destStream);
                    }
                }
            }

            // Find out if we need any extra arguments.
            var extraArgs = extraInstallArgs?.ToList() ?? new List<string>();
            if (!String.IsNullOrWhiteSpace(prefix)) { extraArgs.Add($"--prefix=\"{prefix}\""); }

            Process? process = null;
            try
            {
                process = Process.Start(new ProcessStartInfo
                {
                    FileName = "jupyter",
                    Arguments = $"kernelspec install \"{kernelSpecDir}\" --name=\"{kernelName ?? properties.KernelName}\" {String.Join(" ", extraArgs)}"
                });
            }
            catch (Win32Exception ex)
            {
                System.Console.ForegroundColor = ConsoleColor.Red;
                if (ex.NativeErrorCode == 2)
                {
                    System.Console.Error.WriteLine(
                        "[ERROR] " +
                        $"Could not install {properties.KernelName} into your Jupyter configuration, " +
                        "as `jupyter` was not found on your PATH. " +
                        "Please make sure that Jupyter is installed and is on your PATH. " +
                        "If you are using conda or venv, please " +
                        "make sure that you have the correct environment activated.\n"
                    );
                }
                else
                {
                    System.Console.Error.WriteLine(
                        "[ERROR] " +
                        $"An exception occurred while trying to call `jupyter` to install {properties.KernelName} " +
                        "into your Jupyter configuration.\n"
                    );
                }
                System.Console.ResetColor();
                System.Console.Error.WriteLine(
                    "Full exception details:\n" + ex.ToString()
                );
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex);
                return -2;
            }

            process?.WaitForExit();
            
            // Recursively delete all files and subdirectories in temp directory.
            Directory.Delete(tempKernelSpecDir, true);
            return process?.ExitCode ?? -1;
        }