C# 启动一个进程,如果其中一个线程占用CPU,则暂停该进程

C# 启动一个进程,如果其中一个线程占用CPU,则暂停该进程,c#,.net,visual-c++,process,skype,C#,.net,Visual C++,Process,Skype,有一种说法是,Windows 8上的Skype在一些用户的PC上占据了100%的CPU核心。包括我的!有一个: 下载并运行最新版本的process explorer。() Skype运行时,在活动程序列表中搜索Skype.exe并双击它 转到“线程”选项卡,挂起或杀死空闲时消耗最高资源的Skype线程。(比如50%以上的CPU) 我在每次重启后手动操作这个问题,所以我想把上面的步骤自动化,编写一个简单的C++或C语言的“Skype发射器”程序,程序如下: 启动SKYPE.EXE 每1秒醒来一次

有一种说法是,Windows 8上的Skype在一些用户的PC上占据了100%的CPU核心。包括我的!有一个:

  • 下载并运行最新版本的process explorer。()
  • Skype运行时,在活动程序列表中搜索Skype.exe并双击它
  • 转到“线程”选项卡,挂起或杀死空闲时消耗最高资源的Skype线程。(比如50%以上的CPU)
  • 我在每次重启后手动操作这个问题,所以我想把上面的步骤自动化,编写一个简单的C++或C语言的“Skype发射器”程序,程序如下:

    • 启动SKYPE.EXE
    • 每1秒醒来一次,看看是否有一个特定的Skype线程占用了进程中98%以上的CPU周期
    • 如果找到,则挂起该线程并退出启动程序进程
    • 否则,最多循环10次,直到找到坏线程

    在快速的谷歌搜索之后,我被Win32线程枚举API吓坏了,而这个“查找并杀死/挂起邪恶线程”的问题似乎相当普遍,所以我想知道是否有一个现有的示例可以重复使用。有什么建议吗?

    在经过更多的谷歌搜索和powershell(太多的安全问题,对新手来说太混乱)和WMI(比需要的更难)的一些死胡同后,我终于找到了一个很好的解决方案。这很容易适应在挂起罪犯之前首先检查每个线程的CPU时间

    这是代码。只需编译并进入您的启动菜单,Skype将不再加热您的办公室

    // code adapted from 
    // http://social.msdn.microsoft.com/Forums/en-US/d51efcf0-7653-403e-95b6-bf5fb97bf16c/suspend-thread-of-a-process
    
    using System;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Threading;
    using System.ComponentModel;
    
    namespace SkypeLauncher
    {
        class Program
        {
            static void Main(string[] args)
            {
                Process[] procs = Process.GetProcessesByName("skype");
                if (procs.Length == 0)
                {
                    Console.WriteLine("Skype not loaded. Launching. ");
                    Process.Start(Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES(X86)%\Skype\Phone\Skype.exe"));
                    Thread.Sleep(8000); // wait to allow skype to start up & get into steady state
                }
    
                // wait to allow skype to start up & get into steady state, where "steady state" means
                // a lot of threads created
                Process proc = null;
                for (int i = 0; i < 50; i++)
                {
                    procs = Process.GetProcessesByName("skype");
                    if (procs != null)
                    {
                        proc = procs[0];
                        if (proc.Threads.Count > 10)
                            break;
                    }
                    Thread.Sleep(1000); // wait to allow skype to start up & get into steady state
                }
    
                // try multiple times; if not hanging after a while, give up. It must not be hanging!
                for (int i = 0; i < 50; i++)    
                {
                    // must reload process to get updated thread time info
                    procs = Process.GetProcessesByName("skype");
                    if (procs.Length == 0)
                    {
                        Console.WriteLine("Skype not loaded. Exiting. ");
                        return;
                    }
                    proc = procs[0];
    
                    // avoid case where exception thrown if thread is no longer around when looking at its CPU time, or
                    // any other reason why we can't read the time
                    var safeTotalProcessorTime = new Func<ProcessThread, double> (t => 
                        {
                            try { return t.TotalProcessorTime.TotalMilliseconds; }
                            catch (InvalidOperationException) { return 0; }
                        }
                    );
    
                    var threads = (from t in proc.Threads.OfType<ProcessThread>()
                                      orderby safeTotalProcessorTime(t) descending
                                      select new  
                                      {
                                          t.Id, 
                                          t.ThreadState, 
                                          TotalProcessorTime = safeTotalProcessorTime(t),  
                                      } 
                                  ).ToList();
                    var totalCpuMsecs = threads.Sum(t => t.TotalProcessorTime);
                    var topThread = threads[0];
                    var nextThread = threads[1];
                    var topThreadCpuMsecs = topThread.TotalProcessorTime;
                    var topThreadRatio = topThreadCpuMsecs / nextThread.TotalProcessorTime;
    
                    // suspend skype thread that's taken a lot of CPU time and 
                    // and it has lots more CPU than any other thread. 
                    // in other words, it's been ill-behaved for a long time!
                    // it's possible that this may sometimes suspend the wrong thread, 
                    // but I haven't seen it break yet. 
                    if (topThreadCpuMsecs > 10000 && topThreadRatio > 5)
                    {
                        Console.WriteLine("{0} bad thread. {0:N0} msecs CPU, {1:N1}x CPU than next top thread.",
                            topThread.ThreadState == System.Diagnostics.ThreadState.Wait ? "Already suspended" : "Suspending",
                            topThreadCpuMsecs, 
                            topThreadRatio);
                        Thread.Sleep(1000);
    
                        IntPtr handle = IntPtr.Zero;
                        try
                        {
                            //Get the thread handle & suspend the thread
                            handle = OpenThread(2, false, topThread.Id);
                            var success = SuspendThread(handle);
                            if (success == -1)
                            {
                                Win32Exception ex = new Win32Exception(Marshal.GetLastWin32Error());
                                Console.WriteLine(ex.Message);
                            }
                            Console.WriteLine("Exiting");
                            Thread.Sleep(1000);
                            return;
                        }
                        finally
                        {
                            if (handle != IntPtr.Zero)
                                CloseHandle(handle);
                        };
                    }
    
                    Console.WriteLine("Top thread: {0:N0} msecs CPU, {1:N1}x CPU than next top thread. Waiting.",
                        topThreadCpuMsecs,
                        topThreadRatio);
    
                    Thread.Sleep(2000); // wait between tries
                }
                Console.WriteLine("No skype thread is ill-behaved enough. Giving up.");
            }
            [DllImport("kernel32.dll", SetLastError = true)]
            private static extern int SuspendThread(IntPtr hThread);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool CloseHandle(IntPtr handle);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            private static extern
            IntPtr OpenThread(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)]bool bInheritHandle, int dwThreadId);
        }
    }
    
    //改编自
    // http://social.msdn.microsoft.com/Forums/en-US/d51efcf0-7653-403e-95b6-bf5fb97bf16c/suspend-thread-of-a-process
    使用制度;
    使用System.Linq;
    使用System.Threading.Tasks;
    使用System.Runtime.InteropServices;
    使用系统诊断;
    使用系统线程;
    使用系统组件模型;
    命名空间SkypeLauncher
    {
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    Process[]procs=Process.getProcessByName(“skype”);
    如果(procs.Length==0)
    {
    Console.WriteLine(“Skype未加载。正在启动”);
    Process.Start(Environment.ExpandEnvironmentVariables(@“%PROGRAMFILES(X86)%\Skype\Phone\Skype.exe”);
    Thread.Sleep(8000);//等待skype启动并进入稳定状态
    }
    //等待skype启动并进入稳定状态,“稳定状态”的意思是
    //创建了很多线程
    processproc=null;
    对于(int i=0;i<50;i++)
    {
    procs=Process.getProcessByName(“skype”);
    如果(procs!=null)
    {
    proc=procs[0];
    如果(proc.Threads.Count>10)
    打破
    }
    Thread.Sleep(1000);//等待skype启动并进入稳定状态
    }
    //尝试多次;如果一段时间后没有挂起,就放弃。一定不要挂起!
    对于(int i=0;i<50;i++)
    {
    //必须重新加载进程才能获得更新的线程时间信息
    procs=Process.getProcessByName(“skype”);
    如果(procs.Length==0)
    {
    Console.WriteLine(“Skype未加载。正在退出”);
    返回;
    }
    proc=procs[0];
    //避免在查看线程的CPU时间时,如果线程不再存在而引发异常,或者
    //还有其他我们看不到时间的原因吗
    var safeTotalProcessorTime=新函数(t=>
    {
    请尝试{return t.TotalProcessorTime.totalMillistics;}
    捕获(InvalidOperationException){返回0;}
    }
    );
    var threads=(来自proc.threads.OfType()中的t)
    orderby safeTotalProcessorTime(t)递减
    选择新的
    {
    t、 身份证,
    t、 ThreadState,
    TotalProcessorTime=安全TotalProcessorTime(t),
    } 
    ).ToList();
    var totalCpuMsecs=threads.Sum(t=>t.TotalProcessorTime);
    var topThread=线程[0];
    var nextThread=threads[1];
    var topThreadCpuMsecs=topThread.TotalProcessorTime;
    var topThreadRatio=topThreadCpuMsecs/nextThread.TotalProcessorTime;
    //挂起占用大量CPU时间和内存的skype线程
    //而且它的CPU比任何其他线程都多。
    //换句话说,它已经坏了很长时间了!
    //这可能有时会挂起错误的线程,
    //但我还没看到它坏掉。
    如果(topThreadCpuMsecs>10000&&topThreadRatio>5)
    {
    WriteLine(“{0}个坏线程。{0:N0}毫秒CPU,{1:N1}个CPU比下一个顶级线程长。”,
    topThread.ThreadState==System.Diagnostics.ThreadState.Wait?“已挂起”:“挂起”,
    topThreadCpuMsecs,
    顶丝率);
    睡眠(1000);
    IntPtr handle=IntPtr.Zero;
    尝试
    {
    //获取线程句柄并挂起线程
    handle=OpenThread(2,false,topThread.Id);
    var success=SuspendThread(句柄);
    如果(成功==-1)