2010hook 发表于 2020-6-14 08:18:40

如何用一行PECMD命令,实现PnPUtil输出输入?

本帖最后由 2010hook 于 2020-6-14 08:58 编辑

目标:先枚举已安装的第三方驱动,然后删除对应DriverStore文件。
PnPUtil /enum-drivers
PnPUtil /delete-driver *.inf /force
要求1:用一行简洁的PECMD命令实现,以便写到注册表。并且能与TEAM命令共存。不可调用CMD。
要求2:如果指定只删除oem*这类驱动,又该怎么写?我想看怎么截取字符。

非常感谢!

红毛樱木 发表于 2020-6-14 09:33:01

一行代码,套起来很晕。
多几行呗。
exec* -err+ &a=PnPUtil.exe /enum-drivers
MESS %&a%

2010hook 发表于 2020-6-14 14:09:26

本帖最后由 2010hook 于 2020-6-14 21:53 编辑

红毛樱木 发表于 2020-6-14 09:33
一行代码,套起来很晕。
多几行呗。
exec* -err+ &a=PnPUtil.exe /enum-drivers

输出结果包含一些空行和不需要的信息,如何准确获取所需要的行?如何准确获取包含指定字符的行?
比如:末尾是 .inf 的行,文件名长短不一。

感觉还是CMD语法简单。

dos时代菜鸟 发表于 2020-6-14 18:04:28

本帖最后由 dos时代菜鸟 于 2020-6-14 19:59 编辑

pecmd 可以实现 命令输出 文本流 的精确获取,

参考这个 pecmd 脚本


envi drv3x=某个 inf 文件

EXEC* &drv_result=!pnputil -i -a "%drv3x%"    ``尝试安装并将结果信息存入变量 drv_result
read -*,6,Line,&drv_result``根据 drv_result 获取 ome inf 缓存驱动inf名称
mstr oem_name=<2>%line%
ifex x:\windows\inf\%oem_name%,Exec =!pnputil /delete-driver "%oem_name%" /force``强行删除缓存

红毛樱木 发表于 2020-6-14 21:39:45

ENVI^ EnviMode=1
SET$ &NL=0d 0a//设置&NL变量为换行符
EXEC* -err+ -hide &PnPUtilInfos=PnPUtil.exe -e//读取PnPUtil.exe返回信息
LPOS* * ,*&FixLines=.inf%&NL%,,&PnPUtilInfos    //获取以“.inf”+“换行符”为结尾的行号
FORX *v &FixLines,&Lines,
{*
    READ -*,%&Lines%,&OemInfInfo,&PnPUtilInfos//读取以“.inf”+“换行符”为结尾的行的数据
    MSTR * &OemInfName=<-1>&OemInfInfo//获取改行的inf文件名全称
    MESS. %&OemInfName%<这里执行你要执行的命令>
}


这只是一种方法

感觉LPOS换成用SED的表达式可能更高级,不会正则表达式,有高手来个SED的不?

2010hook 发表于 2020-6-14 21:51:54

PECMD复杂到,我看了两晚都不知道用什么命令,更别说诸多参数。

15106680608 发表于 2020-6-14 21:56:22

谢谢分享

nttwqz 发表于 2020-6-14 22:31:32

2010hook 发表于 2020-6-14 21:51
PECMD复杂到,我看了两晚都不知道用什么命令,更别说诸多参数。

所以,我也不愿意学PECMD,还不如学学真正的编程语言。

红毛樱木 发表于 2020-6-14 23:00:17

2010hook 发表于 2020-6-14 21:51
PECMD复杂到,我看了两晚都不知道用什么命令,更别说诸多参数。

多用几个命令,多几次就适应PECMD的语法了。

2010hook 发表于 2020-6-14 23:00:44

dos时代菜鸟 发表于 2020-6-14 18:04
pecmd 可以实现 命令输出 文本流 的精确获取,

参考这个 pecmd 脚本

改成这样,执行失败,未删除。
team exec* -err+ &oem=pnputil.exe /enum-drivers|read -*,*,line,&oem|exec* pnputil /delete-driver %line% /force

2010hook 发表于 2020-6-14 23:03:48

本帖最后由 2010hook 于 2020-6-14 23:17 编辑

红毛樱木 发表于 2020-6-14 21:39
正则式,用于匹配字符格式,似乎不能判断是否为指定字符。

改成这样,未成功删除:
ENVI^ EnviMode=1
SET$ &NL=0d 0a
EXEC* -err+ -hide &PnPUtilInfos=pnputil.exe /enum-drivers
LPOS* * ,*&FixLines=.inf%&NL%,,&PnPUtilInfos
FORX *v &FixLines,&Lines,
{*
    READ -*,%&Lines%,&OemInfInfo,&PnPUtilInfos
    MSTR * &OemInfName=<-1>&OemInfInfo
    EXEC* pnputil /delete-driver "%&OemInfName%" /force
}

2010hook 发表于 2020-6-14 23:08:12

算了,PECMD语法过于繁琐,还是改用cmd,简洁清晰,成功率高。
exec *cmd /c "for /f %%a in ('pnputil /enum-drivers') do (if /i "%%~xa" equ ".inf" pnputil /delete-driver %%a /force)"

slore 发表于 2020-6-14 23:12:37

本帖最后由 slore 于 2020-6-14 23:20 编辑

如果语法设计少些符号,像常规语言这样自然就好了,
exec('pnputil.exe /enum-drivers').find('oem*inf').each(inf)(exec('pnputil /delete-driver ' + inf + ' /force'))

不然还还是 for + findstr 简单直接。
for /f "tokens=2 delims=:" %%i in ('pnputil.exe /enum-drivers^|findstr "oem.*inf"') do echo pnputil /delete-driver %%i /force'

不用看帮助,基本上一次cmd打出来就能用。

2010hook 发表于 2020-6-14 23:36:22

slore 发表于 2020-6-14 23:12
如果语法设计少些符号,像常规语言这样自然就好了,




你打算抽空重写一个吗?

红毛樱木 发表于 2020-6-14 23:38:06

本帖最后由 红毛樱木 于 2020-6-14 23:42 编辑

2010hook 发表于 2020-6-14 23:03
正则式,用于匹配字符格式,似乎不能判断是否为指定字符。

改成这样,未成功删除:
ENVI^ EnviMode=1
SET$ &NL=0d 0a//设置&NL变量为换行符
EXEC* -err+ -hide &PnPUtilInfos=PnPUtil.exe -e//读取PnPUtil.exe返回信息
LPOS* * ,*&FixLines=.inf%&NL%,,&PnPUtilInfos    //获取以“.inf”+“换行符”为结尾的行号
FORX *v &FixLines,&Lines,
{*
    READ -*,%&Lines%,&OemInfInfo,&PnPUtilInfos//读取以“.inf”+“换行符”为结尾的行的数据
    MSTR * &OemInfName=<-1>&OemInfInfo//获取改行的inf文件名全称
    //MESS. %&OemInfName%<这里执行你要执行的命令>
    EXEC -wait -hide PnPUtil.exe -f -d %&OemInfName%
}


测试成功,没问题。EXEC* &PnPUtilInfos=
这种有返回信息的获取,自动加-wait的

这里的
EXEC -wait -hide PnPUtil.exe -f -d %&OemInfName%
不需要返回信息,要自己加-wait
语法帮助里有说明的。


需要用最新版的PECMD2012才可以的。http://bbs.wuyou.net/forum.php?mod=viewthread&tid=205402


2010hook 发表于 2020-6-14 23:48:43

红毛樱木 发表于 2020-6-14 23:38
测试成功,没问题。EXEC* &PnPUtilInfos=
这种有返回信息的获取,自动加-wait的



我看只有2018stable可供下载。
对了,精简版和无IMd版有什么区别么?

slore 发表于 2020-6-14 23:55:47

2010hook 发表于 2020-6-14 23:36
你打算抽空重写一个吗?
需要重写么?直接cmd就可以了。cmd做不到的用pecmd,
非要都用pecmd的话,有点折磨自己了。学习曲线高,也不通用。
不是专业的话,能解决问题也无性能影响写脚本就行了。

作为启动管理器,也就快捷方式和固定任务栏还有隐藏运行3个命令需要额外写(100行左右就够了)。
上面是lua语言的写法。WinXShell可以用,不用自己做解析。

其他子命令功能不是必须的。
即便上面的命令也有shortcut.exe, PinTool.exe, PinUtil.exe, hiderun.exe, nircmd.exe ... 小命令多的很。

有点跑题了,用自己习惯的擅长的就行。也不要追求1行代码,pecmd多写几行清楚的话,
多些几行也没啥问题啊。
目前对我来说cmd+lua够用,作为开发者自己也可以随意改造扩展,不会花费时间另写命令,
对于绝大部分人pecmd也足够用。


红毛樱木 发表于 2020-6-15 00:07:42

slore 发表于 2020-6-14 23:55
需要重写么?直接cmd就可以了。cmd做不到的用pecmd,
非要都用pecmd的话,有点折磨自己了。学习曲线高, ...

适合自己的才是最好的。

dos时代菜鸟 发表于 2020-6-15 08:11:19

本帖最后由 dos时代菜鸟 于 2020-6-15 08:50 编辑

2010hook 发表于 2020-6-14 23:00
改成这样,执行失败,未删除。
你得先熟悉 pnputil的命令输出,
他的 第六行 中的 第二个单词是 他在驱动安装完毕后生成的oem 类 驱动的名字,也就是驱动缓存对应的 inf ,把这个 名字用 pecmd 的文本流操作指令 弄出来,再 用 pnputil 把这个 oem*.inf强行卸载,他对应的 缓存也就没有了呗。

如果用 pnputil.exe /enum-drivers 获取当前系统所有的 oem 也不难,找出每行第二个单词前三个字母是 oem 的,就行呗。
    ENVI^ EnviMode=1
    Exec* &oem_s=!PnPUtil.exe -e
    envi. oem_XXX=
    Forx *NL &oem_s,oem_x,
    {
            mstr oem_x2=<2>,%oem_x%
            mstr oem_x3=0,3,%oem_x2%
            ifex '%oem_x3%'='oem',
            {
                  envi.oem_XXX=%oem_xxx%\n%oem_x2%
            }
    }
    mess %oem_xxx%


2010hook 发表于 2020-6-15 11:36:09

本帖最后由 2010hook 于 2020-6-15 13:36 编辑

dos时代菜鸟 发表于 2020-6-15 08:11
你得先熟悉 pnputil的命令输出,
他的 第六行 中的 第二个单词是 他在驱动安装完毕后生成的oem 类...
非常感谢耐心讲解,我慢慢学习。
大家不要被oem字样所误导,用某些第三方工具集成驱动,名字是原始文件名,不带oem字样。只要列出的inf都属第三方。
我这贴提及oem,原本想学习pecmd怎么提取字符串,没想到其繁琐程度远超想象。

红毛樱木 发表于 2020-6-15 12:26:46

2010hook 发表于 2020-6-15 11:36
非常感谢耐心讲解,我慢慢学习。
大家不要被oem字样所误导,用某些第三方工具集成驱动,名字是原始文件 ...

我贴的示例代码,按你要求一直不差的弄得哎

slore 发表于 2020-6-15 12:49:18

2010hook 发表于 2020-6-15 11:36
非常感谢耐心讲解,我慢慢学习。
大家不要被oem字样所误导,用某些第三方工具集成驱动,名字是原始文件 ...

原本想学习pecmd怎么提取字符串,没想到其繁琐程度远超想象。

那是PECMD作者把功能实现的太复杂,支持更多复杂要求。

比如,批处理默认for就是一行行的内容分割。

PECMD一段内容你可以随意分割,所以需要NL,或者
SET$ &NL=0d 0a//设置&NL变量为换行符

这就增加了命令的使用难度。多少人知道0d 0a是啥意思?

另外pecmd的命令按设计来说是支持各种编码以及二进制模式,不限定为文本,所以
使用复杂度就上去了。

字符串操作看上面的例子就是 mstr命令吧,不过貌似不支持嵌套,

mstr oem_x2=<2>,%oem_x%
mstr oem_x3=0,3,%oem_x2%

要分好几步骤拆分。

单词获取<数字>,源字符串
字符串截取起始位置,长度,源字符串

再多了些引入的临时变量会更多,不知道是否支持 正则表达式,不然的话可以一次性取出。

红毛樱木 发表于 2020-6-15 13:32:28

slore 发表于 2020-6-15 12:49
那是PECMD作者把功能实现的太复杂,支持更多复杂要求。

比如,批处理默认for就是一行行的内容分割 ...

SED命令支持正常表达式,可是不会写高级的正则表达式。。。

dos时代菜鸟 发表于 2020-6-15 21:52:27

2010hook 发表于 2020-6-15 11:36
非常感谢耐心讲解,我慢慢学习。
大家不要被oem字样所误导,用某些第三方工具集成驱动,名字是原始文件 ...

那就换个思路,找个关键词,设置关键词是 “发布名称:” ,中文环境下测试成功。



ENVI^ EnviMode=1
envi X_sing=发布名称:

    Exec* &oem_s=!PnPUtil.exe -e
    envi. oem_XXX=
    Forx *NL &oem_s,oem_x,
    {
            mstr oem_x1,oem_x2=<1><2>%oem_x%
            ifex '%oem_x1%'='%X_sing%',
            {
                  envi.oem_XXX=%oem_xxx%\n%oem_x2%
            }
    }
    mess %oem_xxx%




页: [1]
查看完整版本: 如何用一行PECMD命令,实现PnPUtil输出输入?