草庐IT

windows - 检测 "suspended"Windows 8/10 进程

coder 2024-06-20 原文

Windows 8/10 中的 UWP(或“Metro”)应用程序不在前台时可以暂停。处于此状态的应用程序继续存在但不再消耗 CPU 时间。引入此更改似乎是为了提高平板电脑和手机等低功耗/存储设备的性能。

检测处于这种状态的进程的最优雅、最简单的方法是什么?

目前我可以看到 2 种可能的解决方案:

  1. 调用 NtQuerySystemInformation() 并枚举每个进程和每个线程。如果所有线程都处于挂起状态,则进程被“挂起”。这种方法将需要大量代码,而且关键的是 NtQuerySystemInformation() 只是半文档化的,可能会在未来的操作系统中被删除。 NtQueryInformationProcess() 也可能针对相同的问题提供类似的解决方案。

  2. 调用 GetProcessTimes() 并记录每个进程的计数器。等待一些较长的时间(分钟)并再次检查。如果进程计数器未更改,则假定进程已挂起。我承认这是一个 hack,但如果时间足够长,可能会奏效。

有没有更优雅的方式?

最佳答案

为此存在PROCESS_EXTENDED_BASIC_INFORMATION - 本answer中描述的标志的含义.你需要 IsFrozen 标志。因此您需要具有 PROCESS_QUERY_LIMITED_INFORMATION 访问权限的开放进程(要对所有进程执行此操作,您需要在 token 中启用 SE_DEBUG_PRIVILEGE)。并使用 ProcessBasicInformationPROCESS_EXTENDED_BASIC_INFORMATION 调用 NtQuerySystemInformation作为输入。为了枚举所有进程,我们可以使用 NtQuerySystemInformationSystemProcessInformation。当然可以并使用 CreateToolhelp32Snapshot + Process32First + Process32Next 但是这个 api 效率很低,比较直接调用 NtQuerySystemInformation

也可以枚举进程中的所有线程并检查它的状态,如果状态等待 - 等待原因。这非常简单,因为所有这些信息都已经通过使用 SystemProcessInformation 调用 NtQuerySystemInformation 返回了。有了这个,我们就不需要开放流程了。通常这两种方式都会给出相同的结果(对于暂停/卡住)进程,但是使用 IsFrozen 是最正确的解决方案。

void PrintSuspended()
{
    BOOLEAN b;
    RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &b);

    ULONG cb = 0x1000;
    NTSTATUS status;
    do 
    {
        status = STATUS_INSUFFICIENT_RESOURCES;

        if (PBYTE buf = new BYTE[cb])
        {
            if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
            {
                union {
                    PBYTE pb;
                    SYSTEM_PROCESS_INFORMATION* spi;
                };

                pb = buf;

                ULONG NextEntryOffset = 0;
                do 
                {
                    pb += NextEntryOffset;

                    if (!spi->UniqueProcessId)
                    {
                        continue;
                    }

                    if (HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, 
                        (ULONG)(ULONG_PTR)spi->UniqueProcessId))
                    {
                        PROCESS_EXTENDED_BASIC_INFORMATION pebi;
                        if (0 <= NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pebi, sizeof(pebi), 0) &&
                            pebi.Size >= sizeof(pebi))
                        {
                            if (pebi.IsFrozen)
                            {
                                DbgPrint("f:%x %wZ\n", spi->UniqueProcessId, spi->ImageName);
                            }
                        }
                        CloseHandle(hProcess);
                    }

                    if (ULONG NumberOfThreads = spi->NumberOfThreads)
                    {
                        SYSTEM_THREAD_INFORMATION* TH = spi->TH;
                        do 
                        {
                            if (TH->ThreadState != StateWait || TH->WaitReason != Suspended)
                            {
                                break;
                            }
                        } while (TH++, --NumberOfThreads);

                        if (!NumberOfThreads)
                        {
                            DbgPrint("s:%x %wZ\n", spi->UniqueProcessId, spi->ImageName);
                        }
                    }

                } while (NextEntryOffset = spi->NextEntryOffset);
            }
            delete [] buf;
        }
    } while (status == STATUS_INFO_LENGTH_MISMATCH);
}

关于windows - 检测 "suspended"Windows 8/10 进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50172564/

有关windows - 检测 "suspended"Windows 8/10 进程的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  5. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  6. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  7. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  8. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  9. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  10. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

随机推荐