Board logo

标题: [系统相关] [已解决]批处理如何获取自身进程的PID? [打印本页]

作者: BAT-VBS    时间: 2013-1-18 13:24     标题: [已解决]批处理如何获取自身进程的PID?

本帖最后由 BAT-VBS 于 2013-1-19 11:01 编辑

http://www.bathome.net/thread-4066-1-1.html
这个帖子里面的代码不靠谱,因为系统里面可能不止一个cmd.exe进程在运行。
作者: batman    时间: 2013-1-18 14:20

好像链接中有你想要的答案啊。。。
  1. @echo off
  2. set "mpath=%~0"
  3. wmic process where commandline='cmd /c ""%mpath:\=\\%" "' get processid
  4. pause>nul
复制代码

作者: terse    时间: 2013-1-18 14:21

本帖最后由 terse 于 2013-1-18 14:23 编辑

除非你多次运行 否则应该满足的
我的意思是 PATH 是单一的 就单一“PATH” 文件运行 应是唯一的
作者: BAT-VBS    时间: 2013-1-18 17:06

回复 2# batman


C:\Test>test.bat
无可用范例。

XP SP3 原版系统
作者: BAT-VBS    时间: 2013-1-18 17:07

回复 3# terse


太高深看不懂。
比如我随便打开一个cmd窗口,然后再双击运行test.bat,如果根据cmd.exe的进程来获取pid,很显然是会出错的吧。
作者: CrLf    时间: 2013-1-18 17:28

  1. wmic process where name="wmic.exe" get parentprocessid
复制代码

作者: terse    时间: 2013-1-18 20:08

回复 5# BAT-VBS
首先每次运行TEST.bat都将得到不同PID  运行一次 将得到TEST.bat进程 PID
你可以先运行名称非TEST的其他BAT文件
再运行TEST.bat  得到的仍是TEST.bat进程 PID
当然有另一情况  那就是 你连续运行两次以上TEST.bat  那你将得到多个 TEST.bat 进程 PID
以下内容为 TEST.bat
  1. @echo off
  2. set path_=%0
  3. for /f "usebackq skip=1" %%i in (`"wmic process where commandline='cmd /c "%path_:\=\\% "' get processID"`) do echo %%i
  4. pause
复制代码

作者: BAT-VBS    时间: 2013-1-18 21:50

回复 7# terse


    测试结果见4楼,不知道是我的系统有问题,还是这个方法不通用。
作者: BAT-VBS    时间: 2013-1-18 21:50

回复 6# CrLf


    版主V5
作者: BAT-VBS    时间: 2013-1-18 22:10

我自己写了一个tasklist,不知道是否通用。
  1. @echo off
  2. for /f "tokens=2" %%a in ('tasklist /v ^| findstr /c:"- %0"') do (
  3.     echo %%a
  4. )
  5. pause
复制代码

作者: BAT-VBS    时间: 2013-1-18 22:20

回复 6# CrLf


版主,我发现一个问题。把wmic放到bat文件里面之后,它获取的pid并非此bat的pid,是不是wmic在执行的时候自己会先创建一个子进程?
  1. @echo off
  2. for /f "tokens=2 delims==" %%a in ('wmic process where "name='wmic.exe'" get parentprocessid /value') do (
  3.     set "myPid=%%a"
  4. )
  5. echo,%myPid%
  6. pause
复制代码

作者: CrLf    时间: 2013-1-19 03:56

回复 11# BAT-VBS


    for /f 从命令中获取输入时,实际上是执行了一个 %comspec% /c xxxxxx,待进程退出后解析其输出,所以如果在 for /f 中执行 wmic 获得的将是 for /f 所创建的 cmd.exe 进程 pid。
    要想通过 for /f 获取当前进程 pid,在原方案的基础上有三个延伸方案
1、用临时文件避免产生多余进程
  1. wmic process where name="wmic.exe" get parentprocessid>tmp.txt
  2. for /f "skip=1" %%a in (tmp.txt) do echo %%a
复制代码
2、利用管道的特性,直接解析外部命令输出
  1. wmic process where name="wmic.exe" get parentprocessid|for /f "skip=1" %%a in ('more') do echo %%a
复制代码
3、先获取 for /f 产生的进程pid
  1. for /f "skip=1" %%a in ('"@for /f "skip=1" %%p in ('wmic process where name^="wmic.exe" get parentprocessid') do @wmic process where processid="%%p" get parentprocessid"') do echo %%a
复制代码
但是鉴于 wmic 无论在 xp 还是 win7 下输出都带有多余的回车符,所以建议在解析时这样过滤一下:
  1. for /f %%a in ('copy /z "%~0" nul') do set "回车符=%%a"
  2. for /f "delims=%回车符%" %%a in ("wmic的输出.txt") echo %%a
复制代码
除了通过父进程 pid 和 batman 以脚本路径为依据的办法,还可以通过标题栏来获取:
  1. set "title=%random%"
  2. title %title%
  3. tasklist /fi "windowtitle eq %title%"
  4. ::如果是以管理员权限运行的,则是 tasklist /fi "windowtitle eq 管理员:  %title%*"
复制代码

作者: BAT-VBS    时间: 2013-1-19 11:00

回复 12# CrLf


    感谢大神,学习了。
作者: tmplinshi    时间: 2013-1-19 13:36

2、利用管道的特性,直接解析外部命令输出
wmic process where name="wmic.exe" get parentprocessid|for /f "skip=1" %%a in ('more') do echo %%a ...
CrLf 发表于 2013-1-19 03:56


在管道后面使用 for 以前没想到。学习了。
作者: terse    时间: 2013-1-19 14:04

本帖最后由 terse 于 2013-1-22 15:47 编辑

总感觉 通过父进程得到pid 还是要确认路径的 才可靠

原来确定父进程pid是FOR输出是 for /f 所创建的 cmd.exe 进程 pid
所以错误的认为非路径确认 学习了 解析输出
所以 否定上面 “总感觉 通过父进程得到pid 还是要确认路径的 才可靠” !
作者: CrLf    时间: 2013-1-19 16:29

回复 14# tmplinshi


    管道法来自这里:http://bbs.bathome.net/redirect. ... 1&fromuid=30406
作者: Pale_Cheung    时间: 2013-11-17 13:06

本帖最后由 Pale_Cheung 于 2013-11-17 13:09 编辑
回复  BAT-VBS


    for /f 从命令中获取输入时,实际上是执行了一个 %comspec% /c xxxxxx,待进程退出 ...
CrLf 发表于 2013-1-19 03:56



    windowtitle 局限性是 本 session 里。比如别的远程桌面上的会话,session 0 的(服务,包括计划任务)取不到他们的windowtitle。本session也有些是暂缺。

其他的方法还是收获不小啊。

powershell 倒是有变量直接解决这个问题了。
作者: cjiabing    时间: 2013-11-17 14:43

http://www.bathome.net/viewthread.php?tid=11052
[原创] 批处理与进程




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2