protected override void OnStart(string[] args)
        {
            int count = Environment.ProcessorCount;

            try { CpuIdle = new PerformanceCounter("Processor", "% Idle Time", "_Total", true); }
            catch (Exception) { }
            if (count < 1 || CpuIdle == null)
            {
                WriteLogEntry(2001, "无法监控CPU", true);
                ExitCode = 2001;
                Stop();
                return;
            }
            if (count > 31)
            {
                WriteLogEntry(2001, "CPU太多,此服务不支持拥有超过31个逻辑处理器的系统", true);
                ExitCode = 2002;
                Stop();
                return;
            }
            CpuIdle.NextValue();
            RestrainThreshold = (float)(100.0 - 90.0 / Environment.ProcessorCount);
            IdleThreshold     = (float)(100.0 - 50.0 / Environment.ProcessorCount);
            if (Lagfree.MyPid < 0)
            {
                using (var me = Process.GetCurrentProcess()) Lagfree.MyPid = me.Id;
            }
            Lagfree.SetupCategory();
            RestrainedCount = new PerformanceCounter(Lagfree.CounterCategoryName, Lagfree.CpuRestrainedCounterName, false);
            LastCounts      = new SortedDictionary <int, double>();
            Restrained      = new Dictionary <int, CpuRestrainedProcess>();
            UsageCheckTimer = new Timer(UsageCheck, null, CheckInterval, CheckInterval);
        }
        private List <KeyValuePair <int, ulong> > ObtainPerProcessUsage()
        {
            List <KeyValuePair <int, ulong> >   IOBytes;
            SortedDictionary <int, IO_COUNTERS> Counts = new SortedDictionary <int, IO_COUNTERS>();
            HashSet <int> ForegroundPids = Lagfree.GetForegroundPids();

            Process[] procs      = Process.GetProcesses();
            DateTime  CountsTime = DateTime.UtcNow;

            if ((LastCountsTime - CountsTime).TotalMilliseconds >= CheckInterval * 2)
            {
                LastCounts.Clear();
            }
            IOBytes = new List <KeyValuePair <int, ulong> >(procs.Length);
            ulong SafeSub(ulong a, ulong b) => a >= b ? a - b : 0;

            foreach (var proc in procs)
            {
                try
                {
                    int pid = proc.Id;
                    if (pid == 0 || pid == 4 || pid == Lagfree.MyPid || pid == Lagfree.AgentPid ||
                        ForegroundPids.Contains(pid) ||
                        Lagfree.IgnoredProcessNames.Contains(proc.ProcessName))
                    {
                        continue;
                    }
                    using (SafeProcessHandle hProcess = proc.SafeHandle)
                    {
                        IO_COUNTERS curr = GetIOCounters(hProcess);
                        Counts.Add(proc.Id, curr);
                        if (LastCounts.ContainsKey(proc.Id))
                        {
                            IO_COUNTERS last = LastCounts[proc.Id];
                            IOBytes.Add(new KeyValuePair <int, ulong>(proc.Id,
                                                                      SafeSub(curr.ReadTransferCount, last.ReadTransferCount) +
                                                                      SafeSub(curr.WriteTransferCount, last.WriteTransferCount) +
                                                                      SafeSub(curr.OtherTransferCount, last.OtherTransferCount) +
                                                                      (
                                                                          SafeSub(curr.ReadOperationCount, last.ReadOperationCount) +
                                                                          SafeSub(curr.WriteOperationCount, last.WriteOperationCount) +
                                                                          SafeSub(curr.OtherOperationCount, last.OtherOperationCount)
                                                                      )
                                                                      ));
                        }
                    }
                }
                catch (Win32Exception) { }
                catch (InvalidOperationException) { }
                catch (Exception ex) { WriteLogEntry(3000, ex.GetType().Name + ":" + ex.Message + "\n" + ex.StackTrace, true); }
            }
            IOBytes.Sort(new Comparison <KeyValuePair <int, ulong> >((x, y) => (y.Value > x.Value) ? 1 : ((x.Value > y.Value) ? -1 : 0)));
            LastCounts     = Counts;
            LastCountsTime = CountsTime;
            return(IOBytes);
        }
        private void ForegroundBoost()
        {
            StringBuilder log            = new StringBuilder();
            HashSet <int> ForegroundPids = Lagfree.GetForegroundPids();

            Process[] procs = Process.GetProcesses();
            foreach (var proc in procs)
            {
                try
                {
                    int    pid   = proc.Id;
                    string pname = proc.ProcessName;
                    if (pid == 0 || pid == 4 || pid == Lagfree.MyPid || pid == Lagfree.AgentPid ||
                        Lagfree.IgnoredProcessNames.Contains(proc.ProcessName))
                    {
                        continue;
                    }
                    // Foreground Boost
                    if (ForegroundPids.Contains(pid))
                    {
                        var rproc = new CpuRestrainedProcess()
                        {
                            OriginalPriorityClass = proc.PriorityClass,
                            Process = proc,
                            Revert  = true
                        };
                        try
                        {
                            if (rproc.OriginalPriorityClass != ProcessPriorityClass.AboveNormal &&
                                rproc.OriginalPriorityClass != ProcessPriorityClass.High &&
                                rproc.OriginalPriorityClass != ProcessPriorityClass.RealTime)
                            {
                                proc.PriorityClass = ProcessPriorityClass.AboveNormal;
                                rproc.Process      = proc;
                                rproc.Revert       = true;
                            }
                            log.AppendLine($"已加速前台进程。 进程{pid} \"{pname}\"");
                        }
                        catch (Exception ex)
                        {
                            WriteLogEntry(2002, $"加速前台进程失败,进程{pid} \"{pname}\"{Environment.NewLine}{ex.GetType().Name}:{ex.Message}", true);
                        }
                        Restrained.Add(pid, rproc);
                    }
                    continue;
                }
                catch { }
            }
            if (log.Length > 0)
            {
                WriteLogEntry(1003, log.ToString());
            }
        }
        protected override void OnStart(string[] args)
        {
            if (Lagfree.MyPid < 0)
            {
                using (var me = Process.GetCurrentProcess()) Lagfree.MyPid = me.Id;
            }
            const string PhysicalDiskCategoryName = "PhysicalDisk";
            var          phyDisks  = new PerformanceCounterCategory(PhysicalDiskCategoryName);
            var          instDisks = phyDisks.GetInstanceNames();
            string       SysDrive  = Environment.GetFolderPath(Environment.SpecialFolder.System).Substring(0, 2).ToLowerInvariant();

            foreach (var inst in instDisks)
            {
                if (inst == "_Total")
                {
                    continue;
                }
                if (inst.ToLowerInvariant().Contains(SysDrive))
                {
                    try
                    {
                        if (!HasNominalMediaRotationRate(int.Parse(inst.Split(' ')[0])))
                        {
                            WriteLogEntry(3001, "注意:检测到OS安装在非旋转存储设备上");
                        }
                    }
                    catch (Win32Exception)
                    {
                        WriteLogEntry(3002, "警告:无法检测到OS安装所在存储设备的旋转速度", true);
                    }
                    Disk = new PerformanceCounter(PhysicalDiskCategoryName, "% Idle Time", inst, true);
                    Disk.NextValue();
                    break;
                }
            }
            if (Disk == null)
            {
                WriteLogEntry(2001, "无法监控磁盘", true);
                ExitCode = 2001;
                Stop();
            }
            else
            {
                Lagfree.SetupCategory();
                RestrainedCount = new PerformanceCounter(Lagfree.CounterCategoryName, Lagfree.IoRestrainedCounterName, false);
                Restrained      = new Dictionary <int, HddRestrainedProcess>();
                LastCounts      = new SortedDictionary <int, IO_COUNTERS>();
                UsageCheckTimer = new Timer(UsageCheck, null, CheckInterval, CheckInterval);
            }
        }
        private List <KeyValuePair <int, double> > ObtainPerProcessUsage()
        {
            List <KeyValuePair <int, double> > CpuCounts;
            SortedDictionary <int, double>     Counts = new SortedDictionary <int, double>();
            StringBuilder log            = new StringBuilder();
            HashSet <int> ForegroundPids = Lagfree.GetForegroundPids();

            Process[] procs      = Process.GetProcesses();
            DateTime  CountsTime = DateTime.UtcNow;

            if ((LastCountsTime - CountsTime).TotalMilliseconds >= CheckInterval * 2)
            {
                LastCounts.Clear();
            }
            CpuCounts = new List <KeyValuePair <int, double> >(procs.Length);
            foreach (var proc in procs)
            {
                try
                {
                    int    pid   = proc.Id;
                    string pname = proc.ProcessName;
                    if (pid == 0 || pid == 4 || pid == Lagfree.MyPid || pid == Lagfree.AgentPid ||
                        ForegroundPids.Contains(pid) ||
                        Lagfree.IgnoredProcessNames.Contains(proc.ProcessName))
                    {
                        continue;
                    }
                    // Obtain data
                    double ptime = proc.TotalProcessorTime.TotalMilliseconds;
                    Counts.Add(pid, ptime);
                    if (LastCounts.ContainsKey(pid))
                    {
                        CpuCounts.Add(new KeyValuePair <int, double>(pid, ptime - LastCounts[pid]));
                    }
                }
                catch (Win32Exception) { }
                catch (InvalidOperationException) { }
                catch (Exception ex) { WriteLogEntry(3000, ex.GetType().Name + ":" + ex.Message + "\n" + ex.StackTrace, true); }
            }
            CpuCounts.Sort(new Comparison <KeyValuePair <int, double> >((x, y) => Math.Sign((y.Value - x.Value))));
            LastCounts     = Counts;
            LastCountsTime = CountsTime;
            return(CpuCounts);
        }