找回密码
 加入
搜索
楼主: smooth

[AU3基础] [已解决]请问如何获取cmd后台信息并强行退出cmd?

 火.. [复制链接]
 楼主| 发表于 2014-2-7 12:30:52 | 显示全部楼层
回复 15# hnfeng

你的测试环境和我的不一样,现在不是退不出cmd的问题,而是进入了sqlcmd.exe(微软数据库的脚本工具,类似cmd.exe)而导致代码根本就无法再往下执行(如果是在SciTE中就可以,不知道为什么?)。
发表于 2014-2-7 12:57:12 | 显示全部楼层
本帖最后由 hnfeng 于 2014-2-7 13:02 编辑


知道环境不同,但是原理是一样的啊
你只需把我的代码里面的 title 更换成你的 sqlcmd 的title 就可以了,不管是cmd、sqlcmd、windows程序,都可以关闭的

在 SciTE 中程序会自动关闭@ComSpec,我试着添加 pause 居然也能关闭。编译后就不会自己关闭了, 因为有 等待@ComSpec 结束的命令,所以就一直等在那里。
这样就就需要添加命令去关闭它。另一个帖子已经说过了,很容易理解的吧。

测试时打开任务管理器,留意看看进程列表。

我是初学,看着说明自己测试的,也许不对。
 楼主| 发表于 2014-2-7 13:51:02 | 显示全部楼层
本帖最后由 smooth 于 2014-2-7 13:53 编辑

回复 17# hnfeng

我看了一下你的代码,你把ProcessWaitClose去掉了,这样会导致读不到run的信息的,虽然你有sleep,但是这个时间的长短不好控制的吧。虽然这样能结束cmd.exe等进程,但是这样会导致程序判断出错,违背了程序设计的初衷呀。
发表于 2014-2-7 16:15:11 | 显示全部楼层
本帖最后由 hnfeng 于 2014-2-7 16:35 编辑

回复 18# smooth


我15楼已经说的明白了吧,你没看吧。
把ProcessWaitClose去掉不影响读run的信息,只是能否把信息全部获取的不同,你没试验吧。
延时的长短可以大致控制获取run信息的多少(对于不断有信息输出的run来说),如果run以后窗口信息很快停止,那就更不影响了。

我的代码只是示例,道理一样,你不能照搬,要根据自己的情况修改啊
 楼主| 发表于 2014-2-7 17:55:32 | 显示全部楼层
本帖最后由 smooth 于 2014-2-7 18:03 编辑

回复 19# hnfeng

可能你没明白我的意思哦。你用sleep来替代ProcessWaitClose延时,这样不会导致卡在ProcessWaitClose上,以便执行后面的结束窗口的代码(个人认为应该是结束进程更好),这个道理我知道。但我的意思是说,用sleep来替代ProcessWaitClose,这个本身是不科学的,因为你不知道需要sleep多长时间,可能有的时候需要的时间很短,有的时候需要的时间又很长,设置短了嘛,达不到效果,设置长了嘛,程序停留的时间太长。但是你的方法不失为一种解决的办法,在没有其他办法之前,也只能采用你说的延时方法。非常感谢你的大力解答,谢谢!
 楼主| 发表于 2014-2-7 18:11:01 | 显示全部楼层
本帖最后由 smooth 于 2014-2-7 18:24 编辑

回复 19# hnfeng
#include <Constants.au3>
$GUICtrlRead2 = ""
$foom = Run(@ComSpec & " /c (for /f ""tokens=*"" %i in ('sqlcmd -U sa -P " & $GUICtrlRead2 & " ^| findstr ""缺少参数""') do @echo %i) ", @SystemDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
Sleep(500)
For $i = 1 To 50
    If ProcessExists("cmd.exe") Then ProcessClose("cmd.exe")
    If ProcessExists("sqlcmd.exe") Then ProcessClose("sqlcmd.exe")
Next
$Textm = StdoutRead($foom)
If StringInStr($Textm, "缺少参数") Then
    MsgBox(16, "密码错误", $Textm, "")
Else
    MsgBox(16, "密码错误", "SQL Server数据库sa账户密码正确!", "")
EndIf
非常奇怪啊,当密码为空时,也即是执行sqlcmd -U sa -P 时,虽然cmd窗口也显示信息,但是却检测不到。当密码是正确的时候,好像就直接进入了SQLCMD窗口,没有看到cmd窗口,这种情况就更不晓得怎么去检测了。目前只能检测密码错误时的cmd窗口信息。
发表于 2014-2-7 19:38:02 | 显示全部楼层
回复 21# smooth


1、你的代码有逻辑错误:for $i = 1 to 50  …………
2、关于检测不到cmd,请仔细看看我15楼和17楼的内容,不想重复了
3、关于不等待@ComSpec完成,而是延迟几秒强行关闭就是为了防止卡死在那里。这没什么不科学的。至于延时多久,你要调试啊,像你这样的命令,我估计一两秒就够,安全起见用了4秒
4、看看说明吧,自带的说明很好的。
 楼主| 发表于 2014-2-7 19:51:38 | 显示全部楼层
回复 22# hnfeng
1、for $i = 1 to 50,有什么逻辑错误?不明白;
2、关于检测不到cmd,我感觉你不明白我说的情况。不是一直检测不到,是密码错误时可以,密码为空时不可以;
3、程序运行的情况很多,平台,机器,什么都有的,sleep不能一概而论;
4、帮助就是九阳真经,要看谁练了。我们平时也看的,但是不一定看帮助就能解决所有的问题。
发表于 2014-2-7 20:29:15 | 显示全部楼层
本帖最后由 hnfeng 于 2014-2-7 20:38 编辑

1、延时到了,如果存在cmd(说明卡到那里了)就强行关闭(你要等待它结束才科学?既然卡在那里了,怎么结束),然后获取到信息,如果不存在cmd,说明它的命令已经结束了(因为有 /c 参数),就返回 @error。你干嘛要重复50次?不明白,是不是想逐一关闭所有的cmd?
2、我明白你的意思。“密码错误时可以”因为cmd自己命令结束了,密码正确时不可以,因为进入了你说的sqlcmd,不能自行退出,此时就需要强行关闭了,但是仍能获取到窗口的信息的。你不就是想获取这些信息吗

15楼的内容:
If WinExists("C:\Windows\system32\cmd.exe") Then WinKill("C:\Windows\system32\cmd.exe")
而不是你的:
If ProcessExists("cmd.exe") Then ProcessClose("cmd.exe")
winkill 与ProcessClose不同的,我实验用了ProcessClose就得不到信息了。

16楼的内容:
你只需把我的代码里面的 title 更换成你的 sqlcmd 的title 就可以了,不管是cmd、sqlcmd、windows程序,都可以关闭的
所以你要看看你的 sqlcmd的title:
    If WinExists("cmd的title") Then WinKill("cmd的title")
   If WinExists("sqlcmd的title") Then WinKill("sqlcmd的title")

另外上面说的返回@error不同情况是不同的。例如我在cmd窗里面 findstr 一个标识字符串,找到就返回,找不到就返回@error,间接实现判断cmd命令运行状态的情况。
发表于 2014-2-7 20:41:33 | 显示全部楼层
也许你的情况比较特殊,非我所能理解,如果帮不到你的话,只能表示遗憾了
 楼主| 发表于 2014-2-7 21:41:43 | 显示全部楼层
本帖最后由 smooth 于 2014-2-7 21:45 编辑

回复 24# hnfeng
你已经帮了我的大忙,真心感谢。

另外,你果然是误会了。我说的是密码为空时,此时并没有进入sqlcmd,而是返回cmd,与密码错误时是一样的,但是,奇怪的是就是,密码错误时可以获取cmd信息,而密码为空时却不可以。
同样,密码正确时,是进入了sqlcmd,但是我按照你说的方法,去掉ProcessWaitClose,而改用sleep,然后强行结束sqlcmd,同样无法获取cmd的信息。

另外你说的使用processclose得不到信息,而我确实可以得到的。
 楼主| 发表于 2014-2-7 22:01:30 | 显示全部楼层
回复 24# hnfeng
为了更能说明问题,我上传截图吧!
密码错误时:

密码为空时:

密码正确时:


红色是我搜索的关键字。
三种情况,只有密码正确时是进入了sqlcmd环境的,其他的都是已经退出了cmd环境(按任意键继续,意味着已经退出了cmd环境了),我同样都按照你说的方法去做,只有密码错误时的关键字能搜索得到,其他两种情况下的关键字无法搜索得到。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2014-2-8 09:34:50 | 显示全部楼层
感谢,感谢
发表于 2014-2-8 11:12:53 | 显示全部楼层
本帖最后由 hnfeng 于 2014-2-8 11:14 编辑

回复 27# smooth


    根据图来看,貌似你需要得到3个状态:得到“登录失败”,得到“缺少参数”,进入了SQLCMD

所以不可以再用 findstr 了(findstr只能支持 找到 及 没找到 两种结果)

$foom = Run(@ComSpec & " /c (for /f ""tokens=*"" %i in ('sqlcmd -U sa -P ') do @echo %i) ", @SystemDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
Sleep(500)
$Textm = StdoutRead($foom)

$Textm中含有所有cmd窗口的信息。
查找 $Textm 中指定字符串可以得到前面两种情况,

If WinExists("SQLCMD") Then .......
如果存在SQLCMD窗口,就说明进入了SQLCMD,你再针对这种情况处理
 楼主| 发表于 2014-2-8 12:03:23 | 显示全部楼层
回复 29# hnfeng

你又给我提供了一种处理这个问题的思路,我根据你的思路来改进我的代码,太感谢了。

另外,我搞不懂的是,我测试时固定密码为空这种情况为前提,为什么检测不到不到“缺少参数”这个关键字呢?我一直在测试,找不到原因。注:我测试时固定密码为空这种情况。

另外,WinExists这个函数,如果窗口是隐藏的,还有效吗?我测试了好像不起作用。

这里想问一下,你从什么地方学习到这么多关于截取cmd窗口信息的资料?我找了帮助里没有,可能是我方法不对。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-5-17 15:38 , Processed in 0.074508 second(s), 15 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表