查询语言

向计算机提问

一种语言,既用于窗口的搜索框,也用于 bws list --query。单独一个词会在名称、显示名称、账户和启动路径中搜索。加上字段则缩小范围。共有 21 个字段,相同的文本在工具的两部分中含义相同。

六个能回答实际问题的查询

应该在运行却没有运行的内容

start:auto !status:running

大多数人写的第一个查询,也是 services.msc 完全无法回答的查询。

文件已丢失的服务

file:missing

指向磁盘上不存在的可执行文件的条目。通常是卸载后遗留了注册信息。

未签名,去掉会话噪声

signed:no peruser:no

按用户的服务族会为每个会话生成一个副本,让列表里充满近似重复的条目。这个查询询问的是其余的部分。

已禁用却仍在运行

mismatch:running

配置与状态不一致:一个被服务管理器设为永不启动的条目,却仍在运行。

任何请求调试权限的内容

privilege:SeDebugPrivilege

一种让进程能够打开任何其他进程的特权。值得知道哪些服务请求了它。

工具无法读取的内容

account:?

此会话无法读取其账户的条目。这是 services.msc 连问都问不出的问题。

如何书写查询

检索词

  • 检索词以空格分隔,并且必须全部匹配:没有 and 关键字,因为它不可能有别的含义。
  • 同一个字段写两次是唯一的例外:status:running status:stopped 表示二者之一,因为勾选两个筛选项时写出的就是这个。对数字的两个边界仍然会缩小范围:pid:>1000 pid:<2000 就是二者之间的范围。
  • 检索词前的 ! 表示取反:!status:running。在带有 setlocal EnableDelayedExpansion 的批处理文件中,cmd 会悄无声息地吃掉这个 !,查询便在不知不觉中变成了别的意思:在那里请在引号内写成 ^!。
  • 字段内的逗号表示或:start:manual,disabled。
  • 引号可以保护含有空格或冒号的内容:account:"NT SERVICE\McmSvc"。
  • 原样粘贴的路径,例如 C:\Windows\System32\svchost.exe,会被当作搜索内容,而不是被当作名为 C 的字段。

文本如何匹配

  • name:spool 匹配任何包含它的内容:这是默认行为,因为这是人们对搜索框的预期。
  • name:=spooler 是精确匹配。
  • name:spool* 支持通配符 * 和 ?。
  • name:/^Sql.*/ 是正则表达式,在斜杠内按正则表达式的写法书写:\?、\\ 和逗号在那里是什么意思就是什么意思。一个永远不闭合的斜杠是错误:要搜索斜杠本身,请写成 \/ 或使用引号。
  • 大小写会被忽略,包括 ASCII 之外的字符:波兰语或希腊语的显示名称,无论怎么输入都能匹配。

每个字段都接受的三个词

  • any - 有值,无论是什么
  • none - 确实没有值,该条目没有值
  • ? - 工具无法读取这个字段,或者没有读取它,而这是 services.msc 连问都问不出的问题

输错的值会报错,而不是返回空结果。status:runing 会回答 Did you mean running?,并以代码 2 结束。空列表看起来就像一个答案,而“没有任何匹配”与“你输错了”之间的差别,就是一台干净的计算机与一次什么也没证明的审计之间的差别。在命令行中,任何不会缩小范围的查询同样会被拒绝,所以脚本不会因为一个拼写错误而对整台计算机进行操作。

更多示例

每一个在窗口的搜索框中和在 bws list --query 之后的效果都一样,而且每一个在写到这里之前都在真实的 Windows 上运行过。能找到什么取决于计算机:对于关于故障的问题,空结果正是你想要的答案。

状态与启动类型

查询找到的内容
status:stopPending,startPending卡在停止或启动中:管理单元显示、永远不会结束的等待。
start:auto status:stopped trigger:none设为自动启动、已停止,且不在等待触发器:重启之后值得一读的简短列表。
start:delayed自动,比其他自动条目稍晚启动。
start:manual,disabled status:running启动时没有任何内容会启动它却在运行:有东西请求了它、触发器启动了它,或者有人启动了它。

账户

查询找到的内容
account:localsystem !publisher:microsoft以最强的账户 LocalSystem 运行,且来自 Microsoft 没有签名的文件。关于发布者的查询会自行读取签名,所以需要几秒钟。
!account:localsystem,localservice,networkservice type:ownProcess,sharedProcess在其他任何账户下运行的服务:虚拟账户、托管账户,或某个人自己的账户。
account:"NT SERVICE"服务自己的虚拟账户。引号把这些词放在一起,因为中间有空格。

文件与签名

查询找到的内容
signed:notSigned,untrustedRoot,tampered没有签名,Windows 不信任的证书链,或签名之后被更改的文件。
signed:trusted !publisher:microsoft已签名、受信任,且不是 Microsoft:其他公司放在这台计算机上的软件。
type:driver start:boot,system !signed:trusted在 Windows 启动时加载、而 Windows 不信任其签名的驱动程序。在健康的计算机上应为零。
!path:C:\Windows type:ownProcess有独立进程、其文件位于 Windows 文件夹之外的服务。
path:\AppData\从某人的用户配置文件内部启动:最不应该出现服务的地方。
path:\System32\\ type:ownProcess空格前的反斜杠会让空格成为词的一部分,所以当后面还有其他检索词时,以反斜杠结尾的路径要写两个反斜杠。在查询末尾,一个就够了。

触发器与依赖关系

查询找到的内容
trigger:device status:stopped等待设备到达,因此是有原因的已停止。
trigger:network当请求到达某个网络端点(端口、命名管道或 RPC 接口)时启动。
trigger:stop触发器不仅可以启动、也可以停止的条目。
dependson:Winmgmt需要 WMI 才能运行的条目。
requiredby:SpoolerPrint Spooler 运行所需要的一切,以及这些内容又依次需要的一切。

特权与进程

查询找到的内容
privilege:SeTcbPrivilege请求以操作系统的一部分身份运行。
privilege:SeImpersonatePrivilege !account:localsystem在 LocalSystem 之外的账户下运行时,可以代表客户端执行操作。
sidtype:unrestricted其进程中带有自己的服务 SID,因此权限可以单独指名它。sidtype:restricted 询问的是其进程同时还受写入限制的那些。
type:sharedProcess status:running与其他服务一起运行在共享的 svchost 内。
memory:>200MB占用超过 200 MB 的进程。查询询问内存时,会自动读取内存。
pid:1000-2000位于进程 ID 在 1000 到 2000 之间的进程中。

名称与文本

查询找到的内容
spool单独一个词,在名称、显示名称、账户和启动路径中搜索。
name:=wuauserv恰好是这个名称,而不是仅仅包含它的内容。
name:win*以 win 开头的名称,用通配符书写。
name:/svc$/以 svc 结尾的名称,用正则表达式书写。
description:none完全没有描述,大多数驱动程序都是这样。
description:?Windows 无法提供的描述,通常是因为它指向一个不存在的语言文件。
peruser:templateWindows 为每个已登录会话复制的按用户模板。

每个字段

由程序本身生成,因此这张表不会与工具接受的内容脱节。没有取值列表的字段接受文本、数字或大小:第三列会说明是哪一种。

字段询问的内容取值
name服务名称,即 Windows 用来识别它的那个名称文本
display显示名称,按这台 Windows 的写法文本
description条目对自身的描述文本
type这是哪一类条目driver, kernelDriver, fileSystemDriver, ownProcess, sharedProcess, unknown
peruser它是否属于 Windows 为每个会话生成副本的按用户服务族之一yes, no, template, instance
status它此刻在做什么running, stopped, paused, pending, startPending, stopPending, pausePending, continuePending, unknown
start服务管理器在下次启动时如何处理它automatic, auto, delayed, manual, disabled, boot, system, unknown
account它运行所用的账户,按服务管理器的写法文本,例如 localsystem
pid它所在的进程数字:1234、>1000、100-200
trigger启动或停止它的条件device, ip, domain, firewall, policy, network, custom, state, aggregate, unknown, start, stop
path服务管理器启动的命令行文本
file它所运行的文件是否在磁盘上present, missing
signedWindows 对文件签名的判断,不检查吊销yes, no, trusted, notSigned, untrustedRoot, expired, revoked, tampered, unknown
publisher谁给文件签的名,只有受信任的签名才能证明文本
privilege条目请求的一项特权文本,例如 SeDebugPrivilege
dependson它需要什么服务名称
requiredby它停止时什么会出问题服务名称
sidtype服务 SID 类型unrestricted, restricted, unknown
sddl安全描述符,以文本形式表示文本
memory它的进程正在使用什么带单位的大小:500MB、>1GB、100MB-1GB
mismatch相互矛盾的配置与状态stopped, running

两件值得知道的事

有些字段开销很大,查询它们会自动开启读取

在整台计算机上读取签名需要几秒钟,而内存是一项测量而不是一项设置,所以除非被要求,否则都不会为列表读取它们。提到其中任何一项的查询会自动开启这项读取:你不必在 signed:no 之外再记着加 --signatures。在窗口中,关于签名的查询会说明在签名到达之前答案并不完整,而不是展示一份较短的列表、仿佛那就是答案。

基于无法读取内容得出的结果会明说

如果条目是依据此会话无法读取的字段来判断的,结果会带有一行说明有多少个,因为这样的结果可能缺少条目,或者包含了不该有的条目。这与整个工具遵守的规则相同:读取失败会在答案中可见,绝不会被吞掉。如果发布者仅由证书声称,也会得到同样的处理:在任何非 trusted 的判定旁边,名称会显示为 not verified,而 publisher: 会在单独一行中把该条目计为不确定,所以 !publisher:microsoft 会保留某个在签名后被人更改过的 Microsoft 文件。

命令行参考