public override async Task <OSInfo> GetOSInfoAsync(CancellationToken cancellationToken)
        {
            OSInfo osInfo = default(OSInfo);

            (int exitCode, List <string> outputLines) = await ExecuteProcessAsync("lsb_release", "-d");

            if (exitCode == 0 && outputLines.Count == 1)
            {
                /*
                ** Example:
                ** Description:\tUbuntu 18.04.2 LTS
                */
                osInfo.Name = outputLines[0].Split(':', count: 2)[1].Trim();
            }

            osInfo.Version = await File.ReadAllTextAsync("/proc/version");

            osInfo.Language          = string.Empty;
            osInfo.Status            = "OK";
            osInfo.NumberOfProcesses = Process.GetProcesses().Length;

            // Source code: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/proc/meminfo.c
            Dictionary <string, ulong> memInfo = LinuxProcFS.ReadMemInfo();

            osInfo.TotalVisibleMemorySizeKB = memInfo[MemInfoConstants.MemTotal];
            osInfo.FreePhysicalMemoryKB     = memInfo[MemInfoConstants.MemFree];
            osInfo.AvailableMemoryKB        = memInfo[MemInfoConstants.MemAvailable];

            // On Windows, TotalVirtualMemorySize = TotalVisibleMemorySize + SizeStoredInPagingFiles.
            // SizeStoredInPagingFiles - Total number of kilobytes that can be stored in the operating system paging files—0 (zero)
            // indicates that there are no paging files. Be aware that this number does not represent the actual physical size of the paging file on disk.
            // https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-operatingsystem
            osInfo.TotalVirtualMemorySizeKB = osInfo.TotalVisibleMemorySizeKB + memInfo[MemInfoConstants.SwapTotal];

            osInfo.FreeVirtualMemoryKB = osInfo.FreePhysicalMemoryKB + memInfo[MemInfoConstants.SwapFree];

            (float uptime, float idleTime) = await LinuxProcFS.ReadUptimeAsync();

            osInfo.LastBootUpTime = DateTime.UtcNow.AddSeconds(-uptime).ToString("o");

            try
            {
                osInfo.InstallDate = new DirectoryInfo("/var/log/installer").CreationTimeUtc.ToString("o");
            }
            catch (IOException)
            {
                osInfo.InstallDate = "N/A";
            }

            return(osInfo);
        }
        public override Task <OSInfo> GetOSInfoAsync(CancellationToken cancellationToken)
        {
            ManagementObjectSearcher   win32OsInfo = null;
            ManagementObjectCollection results     = null;

            OSInfo osInfo = default(OSInfo);

            try
            {
                win32OsInfo = new ManagementObjectSearcher("SELECT Caption,Version,Status,OSLanguage,NumberOfProcesses,FreePhysicalMemory,FreeVirtualMemory,TotalVirtualMemorySize,TotalVisibleMemorySize,InstallDate,LastBootUpTime FROM Win32_OperatingSystem");
                results     = win32OsInfo.Get();

                foreach (var prop in results)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    foreach (var p in prop.Properties)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        string name  = p.Name;
                        string value = p.Value.ToString();

                        if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(value))
                        {
                            continue;
                        }

                        switch (name.ToLowerInvariant())
                        {
                        case "caption":
                            osInfo.Name = value;
                            break;

                        case "numberofprocesses":
                            if (int.TryParse(value, out int numProcesses))
                            {
                                osInfo.NumberOfProcesses = numProcesses;
                            }
                            else
                            {
                                osInfo.NumberOfProcesses = -1;
                            }

                            break;

                        case "status":
                            osInfo.Status = value;
                            break;

                        case "oslanguage":
                            osInfo.Language = value;
                            break;

                        case "version":
                            osInfo.Version = value;
                            break;

                        case "installdate":
                            osInfo.InstallDate = ManagementDateTimeConverter.ToDateTime(value).ToUniversalTime().ToString("o");
                            break;

                        case "lastbootuptime":
                            osInfo.LastBootUpTime = ManagementDateTimeConverter.ToDateTime(value).ToUniversalTime().ToString("o");
                            break;

                        case "freephysicalmemory":
                            osInfo.AvailableMemoryKB = ulong.Parse(value);
                            break;

                        case "freevirtualmemory":
                            osInfo.FreeVirtualMemoryKB = ulong.Parse(value);
                            break;

                        case "totalvirtualmemorysize":
                            osInfo.TotalVirtualMemorySizeKB = ulong.Parse(value);
                            break;

                        case "totalvisiblememorysize":
                            osInfo.TotalVisibleMemorySizeKB = ulong.Parse(value);
                            break;
                        }
                    }
                }
            }
            catch (ManagementException)
            {
            }
            finally
            {
                results?.Dispose();
                win32OsInfo?.Dispose();
            }

            return(Task.FromResult(osInfo));
        }