标题: [原创] 批处理与进程 [打印本页]
作者: cjiabing 时间: 2011-2-11 23:01 标题: 批处理与进程
本帖最后由 cjiabing 于 2011-10-10 09:12 编辑
原来发在原创作品区,以为大家都会用批处理操作进程,但后来发现许多人的提问有意无意都会涉及到此问题。因此,特地对“批处理”与“进程”进行总结梳理,并转到教学和资料区,以供查询。
一、常见进程命令
查找或列举进程:【Tasklist 】 这个命令行工具显示应用程序和本地或远程系统上运行的相关任务/进程的列表。
结束进程:【Taskkill】 这个命令行工具可用来结束至少一个进程。可以根据进程 id 或图像名来结束进程。
强制结束进程:【Ntsd】 NTSD -c q -Pn
综合操作进程:【Wmic Process】 wmic process where name="qq.exe"
(一)Tasklist
主要用来获取进程,包括系统进程和程序进程。单纯使用一个tasklist命令便能够获取当前所有进程。
1、参数列表
如果需要获取特定条件下的进程信息,可以使用以下参数列表:
/S system 指定连接到的远程系统。
/U [domain\]user 指定应该在哪个用户上下文执行这个命令。
/P [password] 为提供的用户上下文指定密码。如果忽略,提示输入。
/M [module] 列出所有其中符合指定模式名的 DLL 模块的所有任务。如果没有指定模块名,则显示每个任务加载的所有模块。
/SVC 显示每个进程中的服务。
/V 指定要显示详述信息。
使用举例:
tasklist
::列出所有当前进程。
tasklist /?
::获得tasklist命令的帮助信息。
tasklist /v
::获得每个命令的详细信息。
tasklist /m
::列出每个进程的dll模块。杀毒的时候参考。
tasklist /m QQMusic.dll
::获取包含有“QQMusic.dll”这个模块的进程。又如:tasklist /m wbem*
tasklist /svc
::获得每个进程中的服务项。杀毒的时候可以查阅。
未提到的参数请自学。
其他:
TASKLIST /S system /FO LIST
TASKLIST /S system /U domain\username /FO CSV /NH
TASKLIST /S system /U username /P password /FO TABLE /NH
TASKLIST /FI "USERNAME ne NT AUTHORITY\SYSTEM" /FI "STATUS eq running"
2、筛选器
如果想进行更详细的操作,可以参考以下参数:
/FI filter 显示一系列符合筛选器指定的标准的任务。
/FO format 指定输出格式。有效值: "TABLE"、"LIST"、"CSV"。
/NH 指定栏标头不应该在输出中显示。只对 "TABLE" 和 "CSV" 格式有效。
筛选器:
筛选器名 有效操作符 有效值
----------- --------------- --------------
STATUS eq, ne 正在运行 | 没有响应
IMAGENAME eq, ne 图像名
PID eq, ne, gt, lt, ge, le PID 值
SESSION eq, ne, gt, lt, ge, le 会话编号
SESSIONNAME eq, ne 会话名
CPUTIME eq, ne, gt, lt, ge, le CPU 时间,格式为
hh:mm:ss。
hh - 时,
mm - 分,ss - 秒
MEMUSAGE eq, ne, gt, lt, ge, le 内存使用量(KB)
USERNAME eq, ne 用户名,格式为 [domain\]user
SERVICES eq, ne 服务名
WINDOWTITLE eq, ne 窗口标题
MODULES eq, ne DLL 名
使用举例:
tasklist /fi "imagename eq qq.exe"
::获取指定进程名的进程信息。比较常用,要掌握。
::注意,“/fi”筛选器要用双引号包住。
::eq-等于;ne-不等于;gt-大于;lt-小于;ge-大于等于;le-小于等于。
tasklist /fi "pid eq 4"
::获取指定PID为4的进程。
tasklist /fi "windowtitle eq 无标题 - 记事本"
::获得指定窗口标题的进程,一个空记事本的标题和进程。
tasklist /fi "windowtitle eq 批处理之家 ─ 做最实用的批处理论坛 - Powered by Discuz! - Mictosoft Internet Explorer" /nh
::获得指定窗口标题的进程,批处理之家在IE中的标题。
- @echo off
- title 批处理进程
- for /f "tokens=2" %%a in ('tasklist /fi "windowtitle eq 批处理进程" /nh') do echo 窗口标题为“批处理进程”的PID是:%%a
- pause
复制代码
::获得指定进程的PID。tasklist配合FOR使用,可以获得更多操作空间,比如获得PID、图像名、内存使用等。
tasklist /fi "IMAGENAME eq cmd.exe" /FO TABLE /NH
cmd.exe 3008 0 104 K
::输出(显示)格式为table格式。
tasklist /fi "IMAGENAME eq cmd.exe" /FO csv /NH
"cmd.exe","3008","","0","104 K"
::输出(显示)格式为CSV形式。
tasklist /m /fo list
::输出(显示)格式为列表形式
(二)Taskkill
1、基本用法
许多参数同tasklist。
参数列表:
/S system 指定要连接到的远程系统。
/U [domain\]user 指定应该在哪个用户上下文执行这个命令。
/P [password] 为提供的用户上下文指定密码。如果忽略,提示输入。
/F 指定要强行终止进程。
/FI filter 指定筛选进或筛选出查询的的任务。
/PID process id 指定要终止的进程的PID。
/IM image name 指定要终止的进程的图像名。通配符 '*'可用来指定所有图像名。
/T Tree kill: 终止指定的进程和任何由此启动的子进程。
/? 显示帮助/用法。
使用举例:
taskkill /im iexplore.exe
::结束IE浏览器。
taskkill /f /t /im Storm.exe
::强制结束暴风影音主进程。比较常用,要掌握。
::注意:批处理不是万能的,同样,taskkill也不是万能的。比如360它就结束不了。
taskkill /f /im explorer.exe
::结束资源管理器(桌面)。
::注意:如果你的批处理想在关闭桌面后仍能够正常执行,最好不要用参数“/T”。
::另外:别尝试结束核心系统进程,否则有可能导致系统崩溃,当然也有可能不允许操作。
taskkill /f /t /pid 2368
::结束指定Pid的进程。比较常用,要掌握。
::pid是进程的唯一标识,每个进程打开的时候系统都会随机给它PID,用以区别其它进程。
2、筛选器
至于筛选器等其它参数,帮助说明里的举例:
例如:
TASKKILL /S system /F /IM notepad.exe /T
TASKKILL /PID 1230 /PID 1241 /PID 1253 /T
TASKKILL /F /IM notepad.exe /IM mspaint.exe
TASKKILL /F /FI "PID ge 1000" /FI "WINDOWTITLE ne untitle*"
TASKKILL /F /FI "USERNAME eq NT AUTHORITY\SYSTEM" /IM notepad.exe
TASKKILL /S system /U domain\username /FI "USERNAME ne NT*" /IM *
TASKKILL /S system /U username /P password /FI "IMAGENAME eq note*"
(三)NTSD
强制结束进程,传说比taskkill要强很多,但在当今群魔乱舞的时代,它也像taskill一样被贬得不值一提了。还是那句话,单纯靠批处理命令自身杀进程是很难的,因为批处理不是万能的。
基本用法:NTSD -c q -Pn
使用举例:ntsd -c q -p 2136
注意:它是使用pid结束进程的。遇到无法结束的进程或其它问题时,它会弹出一个新的cmd用以交互,询问你是否继续,一般回车即可继续。但回车后你会发现,继续回车也没能把进程杀掉。
(四)Wmic Process
wmic是一个相当强大的命令,它有一个进程选项Process,利用它我们可以对进程进行更多的操作,比如获得进程的路径等。
1、Wmic Process
::获得所有进程的所有信息,类似于tasklist,但比tasklist要丰富得多了。它的输出结果一般包含以下内容,按输出顺序排列,用空格隔开:
Caption CommandLine CreationClassName CreationDate CSCreationClassName CSName Description ExecutablePath ExecutionState Handle HandleCount InstallDate KernelModeTime MaximumWorkingSetSize MinimumWorkingSetSize Name OSCreationClassName OSName OtherOperationCount OtherTransferCount PageFaults PageFileUsage ParentProcessId PeakPageFileUsage PeakVirtualSize PeakWorkingSetSize Priority PrivatePageCount ProcessId QuotaNonPagedPoolUsage QuotaPagedPoolUsage QuotaPeakNonPagedPoolUsage QuotaPeakPagedPoolUsage ReadOperationCount ReadTransferCount SessionId Status TerminationDate ThreadCount UserModeTime VirtualSize WindowsVersion WorkingSetSize WriteOperationCount WriteTransferCount
2、查找指定进程
使用举例:wmic process where name="qq.exe"
输出内容太多了,我们把内容输出到文本中,记事本不要自动换行,现在可以仔细观察了:
wmic process where name="qq.exe">>c:\qq.txt
挑出一些我们常用的选项:
Caption 图像名 qq.exe
CommandLine 命令行(包含命令和路径,有双引号) "C:\Program Files\Tencent\QQ\Bin\QQ.exe"
ExecutablePath 程序执行路径(没有双引号) C:\Program Files\Tencent\QQ\Bin\QQ.exe
Name 名称 qq.exe
ProcessId 进程PID(变化) 804
现在,我们可以对特定项进行操作了。比如下面的,获取cmd.exe的PID和路径
3、查找指定进程指定项
使用举例:wmic process where name="cmd.exe" get ProcessId,CommandLine
可以用for进一步编辑操作:
- @echo off
- for /f "skip=1 tokens=1,*" %%i in ('"wmic process where name="cmd.exe" get ProcessId,CommandLine"') do echo Cmd的PID是:%%i;命令是:%%j
- pause
复制代码
4、结束指定进程
使用举例:wmic process where name="notepad.exe" call Terminate
::结束记事本进程。
- @echo off
- wmic process where Handle="1248" call Terminate
- pause
- wmic process where caption="iexplore.exe" get ExecutablePath^,Handle
- pause
复制代码
二、综合运用
下面介绍批处理进程命令的一些常见用法。
(一)常见用法
1、如何获得进程的程序路径?
可以考虑的只有:wmic process where name="cmd.exe" get CommandLine,ExecutablePath
其中,ExecutablePath表示程序所在位置的路径;CommandLine表示执行的命令路径。比如,cmd的路径(ExecutablePath)是c:\windows\system32\cmd.exe,但你运行的批处理命令的路径(CommandLine)则不是前面那个路径,而可能是d:\batch\test.bat等其他路径,虽然它们的进程图像名都是cmd.exe。
C:\>wmic process where name="cmd.exe" get ExecutablePath
ExecutablePath
C:\WINDOWS\system32\cmd.exe
C:\WINDOWS\system32\cmd.exe
可以获得程序的真实地址,不过不能获得cmd执行的程序路径
C:\>wmic process where name="cmd.exe" get CommandLine
CommandLine
cmd /c ""C:\Program Files\BatMPlayer\BatMPlayer.bat" "
"C:\WINDOWS\system32\cmd.exe"
C:\WINDOWS\system32\cmd.exe /K "C:\Program Files\BatMPlayer\BatMPlayer.bat" bh
可以获得程序执行的命令和命令中的程序路径,这个程序路径很有意义,但提取路径比较麻烦,一要剥离命令,二要剥离双引号。
再看看两者的差异,一个有双引号,一个么有:
C:\>wmic process where name="qq.exe" get CommandLine
CommandLine
"D:\Program Files\Tencent\QQ\Bin\QQ.exe"
C:\>wmic process where name="qq.exe" get ExecutablePath
ExecutablePath
D:\Program Files\Tencent\QQ\Bin\QQ.exe
2、如何获得进程的PID?
进程PID是进程的唯一身份标识,我们常常用此来区分相同名称的进程,并用它来结束进程。
具体获取方法参考前面的例子。
- for /f "tokens=2" %%a in ('tasklist /fi "IMAGENAME eq cmd.exe" /nh') do echo 进程图像名为“cmd.exe”的PID是:%%a
复制代码
3、如何获取进程的窗口标题?
可以根据图像名、PID等来进行判断,获得标题后还可以进行判断。
- @echo off
- for /f "tokens=1,9*" %%a in ('tasklist /v /FO TABLE /NH') do if /i %%a==cmd.exe echo %%b %%c
- pause
复制代码
其实,有时候我也没想到过“tasklist /v /FO TABLE /NH”能发挥到这种作用,非常难得的发现。
如果把cmd.exe换成qq.exe,如果你打开了QQ聊天窗口,可以获得当前聊天窗口名称(QQ昵称),但是没有找到显示QQ号的方法。
4、tasklist、taskkill、wmic process的效率如何?
与tasklist、taskkill相比,ntds显得罗嗦,而wmic process则显得稍微慢,特别是在一些情况下,wmic往往容易发生错误,比较难以处理。但wmic仍然无可替代,因为它提供了一些tasklist和taskkill所没有的功能,丰富了批处理对进程的操作。tasklist、for、if的组合是最佳的组合,可以实现许多意想不到的功能。
5、为何在FOR中无法判断进程不存在的情况?
- @echo off
- for /f "skip=1 tokens=1,*" %%i in ('"wmic process where name="qq.exe" get ProcessId,CommandLine"') do if not "%%i"=="" (echo Cmd的PID是:%%i;命令是:%%j) else (echo 找不到进程)
- pause
- @echo off
- for /f "skip=1 tokens=1,*" %%i in ('tasklist /fi "WINDOWTITLE eq BatMplayer" /FO list') do if not "%%i"=="" (echo Cmd的PID是:%%i;命令是:%%j) else (echo 找不到进程)
- pause
复制代码
运行结果是:
无可用范例。
请按任意键继续. . .
信息: 没有运行的带有指定标准的任务。
为什么IF后面的“找不到进程”无法显示呢?
原因在于,这几个进程命令只提供找到进程时的处理方案,不提供找不到进出时的处理方案。如果找不到进程,它就会做出上面的错误提示。而且这些错误提示不能在FOR后面用“>nul 2>nul”屏蔽掉,必须用大括号将整个for命令括起来再用“>nul 2>nul”屏蔽。
所以,平时处理此问题时,只需考虑存在进程的状况,无需进行否定判断。
如果确实需要判断进程不存在的状况,可以这样:
- @echo off
- set var=0
- for /f %%a in ('tasklist') do (if /i %%a==ttplayer.exe set var=1)
- if %var%==1 (echo 存在进程) else (echo 进程不存在)
- pause
复制代码
可能用find也可以。
此外,通过以下代码,你或许会对这几个进程命令有更多的想法:
- @echo off
- tasklist|findstr /n /i "cmd.exe"
- pause
- echo:注意,结果在这里:
- tasklist|more|findstr /n /i "cmd.exe"
- pause
复制代码
当你打开几个cmd.exe窗口,并运行该命令时,注意观察结果出来的那一瞬间。第一行结果显示在“请按任意键”的后面来了,明显有一个延迟的过程。似乎命令发送指令到其它容器中,其它容器将信息反馈回来,这个过程比较长,因此产生了延迟。
(二)综合应用
1、区分多个相同名称的进程,并根据指定窗口标题的PID结束进程
- ::当有多个相同的进程名称时,根据进程标题和PID结束进程。
- ::判断CMD.EXE的进程,假如这个进程的标题符合(含有)“正在播放”这个特征的就根据该进程的PID结束该进程。“tokens=2,9”中的2指PID,9指标题,还可以用一个1指进程名称cmd.exe。
-
- for /f "tokens=2,9 delims=: " %%a in ('"tasklist /v /fi "IMAGENAME eq cmd.exe" /FO TABLE /NH"') do (
- if "%%b"=="正在播放" taskkill /f /t /pid %%a>nul 2>nul
- )
复制代码
2、区分多个相同名称的进程,并获得程序自身进程的PID
- @echo off&setlocal enabledelayedexpansion
- ::结束自身以外的任何CMD.EXE进程,以及指定的CMD.exe进程。
-
- title BatMPlayer
- for /f "skip=3 tokens=2" %%a in ('TASKLIST /FI "WINDOWTITLE eq BatMPlayer" /FI "STATUS eq running"') do set pcmd=%%a
- rem 根据进程标题获得程序自身进程PID,前面要先定义TITLE。
-
- for /f "tokens=1,2,9 delims=: " %%a in ('"tasklist /v /fi "IMAGENAME eq cmd.exe" /FO TABLE /NH"') do (
-
- if "%%c"=="正在播放" taskkill /f /t /pid %%b>nul 2>nul
- rem 假如进程图像名为CMD.EXE,并且标题为“正在播放”,则结束该进程。用于结束指定进程。
-
- if /i "%%a"=="cmd.exe" (if not %%b==%pcmd% taskkill /f /t /pid %%b) else (taskkill /f /t /im %%a||NTSD -c q -P %%a)
- rem 假如进程图像名为CMD.EXE,且该图像名不等于本批处理自身进程PID的,就结束该进程。用于结束指定进程以外的其它进程。
- rem 注意:这行行代码包括了上面结束“正在播放”的代码,不要同时使用,有冲突。
- )
- pause
复制代码
3、判断是否存在某个进程
- :play_gc
- ::假如不存在某个进程名称就返回,否则等待给进程结束。
-
- for /f "tokens=1" %%a in ('tasklist /fi "IMAGENAME eq MPLAYER.exe" /FO TABLE /NH') do if /i "%%a"=="mplayer.exe" (ping /n 2 127.0.1>nul&goto play_gc)
- goto :eof
复制代码
可以使用find等命令判断,如:tasklist /v /FO TABLE /NH|find /i "cmd.exe"
(三)实战应用
学会应用批处理处理进程可以实现很多奇妙的功能,以下为本人的一些作品,在一些关键的地方都用到了进程处理,链接可打开:
[系统增强]批处理一键清理系统三剑客 (结束非系统进程,结束非自身的其他所有cmd.exe进程)
[文件管理][分享]两个批处理程序间的参数传递 (获取批处理的窗口标题和PID)
[游戏娱乐]批处理播放器 BatMPlayer 2011 Beta (假如存在某进程就等候该进程结束,一个程序一次只能运行一个)
(四)其他问题
收录一些简单好用的进程类的代码:
限制进程运行
- @echo off
- :loop
- taskkill /f /t 123.exe
- goto loop
- pause
复制代码
保持进程运行
-
- @echo off
- :loop
- start iexplore.exe
- goto loop
复制代码
统计指定名称进程个数
- @echo off
- set n=0
- for /f %%i in ('tasklist^|findstr /i "cmd.exe"') do set /a n+=1&echo %%i
- echo %n%
- pause
复制代码
统计程序一共打开了多少个进程
-
- @echo off
- for /f "tokens=1 delims=[]" %%a in ('cmd /c "wmic process where name="cmd.exe" get CommandLine" ^| find /i "%~f0" ^| find /i /n "%~f0"') do set /a num=%%a-1
- echo 该程序一共打开了 %num% 个。
- pause
复制代码
作者: cjiabing 时间: 2011-8-4 20:09
包括两部分:一是提取进程路径(命令行CommandLine中的路径),二是判断相同路径的进程有几个。可以分拆。提取路径部分有点罗嗦,但在不稳定的WMIC下只能如此了。- @echo off&setlocal enabledelayedexpansion
- ::判断一个批处理程序一共同时打开了多少个(进程)。
- ::包括内容:以图像名、路径等判断进程。可以联合窗口标题等判断,并利用PID杀掉其他打开的进程。
-
- for /f "tokens=1 delims=[]" %%a in ('cmd /c "wmic process where name="cmd.exe" get CommandLine" ^| find /i "%~f0" ^| find /i /n "%~f0"') do set /a num=%%a-1
-
- set "pat=%~f0"
- set img=cmd.exe
- set tit=判断自身是否运行
- title %tit%
-
- for /f "tokens=1,2,9*" %%x in ('tasklist /v /FO TABLE /NH') do if /i %%x==%img% if /i "%%z"=="%tit%" (
- for /f "tokens=1,* delims==" %%a in ('"wmic process where name="%img%" get CommandLine,processid /value"') do for /f "tokens=1,*" %%i in ("%%a %%~b") do (
- if /i "%%i"=="ProcessId" if %%j==%%y for /f "tokens=1-12" %%o in ("!coml!") do for %%m in (%%~o %%~p %%~q %%~r %%~s %%~t %%~u %%~v %%~w %%~x) do if /i not "%%~m"=="cmd" if /i not "%%~m"=="/c" set "var=%%~m"
- if /i "%%i"=="CommandLine" set coml=%%~j
- )
- )
- echo ---------------------------------------------
- echo 进程中的路径是:!var!
- echo 本程序的路径是:!pat!
- echo !var!|find /c /i "!pat!">nul&&echo 同一程序!
- if /i "!var!"=="!pat!" echo 同一程序!
- echo 本程序一共打开了 %num% 个进程。
- echo ---------------------------------------------
- pause
复制代码
作者: yangeren 时间: 2011-8-5 15:07
本帖最后由 yangeren 于 2011-8-5 15:09 编辑
学了不少,我还以为没有加find的例子呢,往后一看,有了,哈哈,不好意思
作者: lxzzr 时间: 2011-8-5 16:59
不稳定的WMIC?
何解??
作者: zaixinxiangnian 时间: 2011-10-10 21:11
是个好贴
但这句提示没有找到匹配的进程- tasklist /fi "windowtitle eq 批处理之家 ─ 做最实用的批处理论坛 - Powered by Discuz! - Mictosoft Internet Explorer" /nh
复制代码
作者: tangqingfu 时间: 2013-6-21 17:04
谢谢版主的分享,收藏学习!
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |