网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Visual Basic
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
本月文章推荐
.用VB尝试新的界面风格.
.怎样限制鼠标移动.
.VB从零开始编外挂(六).
.如何编写高质量的VB代码.
.如何充分扩充VB功能.
.MSOffice开发工具--VBA.
.处理加了admin888的MDB文件.
.创建ActiveX接口以移植Excel工作.
.从文件中提取图标.
.一组VB应用技巧.
.复本操作的对象、属性和方法(3)-.
.VB多类图片数据库存取技巧.
.在VB中通过相对路径引用标准DLL.
.用CallByName函数实现字符动画.
.通过VisualBasic获取网卡地址.
.如何实现VB程序登录admin888加密.
.DataGrid控件的使用三.
.VB数据库数据的选项录入及选项增.
.VisualBasic可以产生四角形以外其.
.VisualBasic菜单在应用程序中的使.

使用Shell指令具有Wait的功能

发表日期:2006-2-27


VB中,常以Shell指令来执行外部程式,然而它在Create该外部process後,立刻
就会回到vb的下一行程式,无法做到等待该Process结束时,才执行下一行指令,
或是说,无法得知该Process是否已结束,甚者,该Process执行到一半,又该如何
中止其执行等等,这些都不是Shell指令所能控制的,因此我们需使API的帮助来完
成。

第一个问题,如何等待shell所Create的process结束後才往後执行vb的程式。
首先要知道的是,每个Process有唯一的一个ProcessID,这是OS给定的,用来
区别每个Process,这个ProcessID(PID)主要可用来取得该Process相对应的一些
资讯,然而要对该Process的控制,却大多透过ProcessHandle(hProcess)。VB
Shell指令的传回值是PID,而非hProcess,所以我们需透过OpenProcess这个API来
取得hProcess而OpenProcess()的第一个叁数,指的是所取得的hProcess所具有的
能力,像PROCESS_QUERY_INFORMATION便是让GetExitCode()可取得hProcess所指
的process之状态,而PROCESS_TERMINATE,便是让TerminateProcess(hProcess..)
的指令能够生效,也就是说,不同叁数设定,使hProcess所具有的权限、能力有所
不同。取得hProcess後便可以使用WaitForSingleObject()来等待hProcess状态的
改变,也就是说,它会等待hProcess所指的process执行完,这个指令才结束,它
第二个叁数所指的是WaitForSingleObject()所要等待的时间(inmilliseconds)
,如果超过所指的时间,就TimeOut而结束WaitForSingleObject()的等待。若要它
无限的等下去,就设定为INFINITE。

pid=Shell("C:\tools\spe3\pe2.exe",vbNormalFocus)
hProcess=OpenProcess(PROCESS_QUERY_INFORMATION,0,pid)
ExitEvent=WaitForSingleObject(hProcess,INFINITE)
CallCloseHandle(hProcess)

上例会无限等待shell指令create之process结束後,才再做後面的vb指令。有
时觉得那会等太久,所以有第二个解决方式:等process结束时再通知vb就好,即
:设定一个公用变数(isDone),当它变成True时代表Shell所Create的Process已结
束。当Process还在执行时,GetExitCodeProcess会传&H103给其第二个叁数,直到
结束时才传另外的数值,如果程式正常结束,那Exitcode=0,否则就得看它如何
结束了。或许有人在其他地方看到loop的地方是LoopwhileExitcode<>0,那
有一点危险,如果以这程子来看,您不是用F4来离开pe2而是用右上方X的结束
doswindow那麽,会因为ExitCode的值永远不会是0,而进入无穷的回圈。

DimpidAsLong
pid=Shell("C:\tools\spe3\pe2.exe",vbNormalFocus)
hProcess=OpenProcess(PROCESS_QUERY_INFORMATION,0,pid)
isDone=False
Do
CallGetExitCodeProcess(hProcess,ExitCode)
Debug.PrintExitCode
DoEvents
LoopWhileExitCode=STILL_ALIVE
CallCloseHandle(hProcess)
isDone=True

另外,如果您的shell所Create的程式,有视窗且为立刻Focus者,可另外用以
下的方式DimpidAsLong
Dimhwnd5AsLong
pid=Shell("c:\tools\spe3\pe2.exe",vbNormalFocus)
hwnd5=GetForegroundWindow()
isDone=False
DoWhileIsWindow(hwnd5)
DoEvents
Loop
isDone=True



而如何强迫shell所Create的process结束呢,那便是
DimaaAsLong
IfhProcess<>0Then
aa=TerminateProcess(hProcess,3838)
EndIf

hProcess便是先前的例子中所取得的那个ProcessHandle,3838所指的是传给
GetExitCodeProcess()中的第二叁数,这是我们任意给的,但最好不要是0,因为
0一般是代表正常结束,当然这样设也不会有错。当然不可设&H103,以这个例子来
看,如果程式正处於以下的LOOP
Do
CallGetExitCodeProcess(hProcess,ExitCode)
Debug.PrintExitCode
DoEvents
LoopWhileExitCode=STILL_ALIVE
Debug.printExitCode

而执行了TerminateProcess(hProcess,3838)那会看到ExitCode=3838。然
而,这个方式在win95没问题,在NT中,可能您要在OpenProcess()的第一个叁数要
更改成PROCESS_QUERY_INFORMATIONOrPROCESS_TERMINATE这样才能Work。不过
良心的建议,非到最後关头,不要使用TerminateProcess(),因不正常的结束,往
往许多程式结束前所要做的事都没有做,可能造成Resource的浪费,甚者,下次再
执行某些程式时会有问题,例如:本人常使用MS-dosShellLink的方式执行一程
式,透过Comport与大电脑的联结,如果Ms-dosShellLink不正常结束,下次再
想Link时,会发现tooManyOpens,这便是一例。

另外,有人使用Shell来执行.bat档,即:
pid=Shell("c:\aa.bat",vbNormalFocus)
可是却遇上aa.bat结束了,但ms-dos的Window却仍活着,那可以用以下的方式来做
pid=Shell("c:\command.com/cc:\aa.bat",vbNormalFocus)
那是执行Command.com,而Command.com指定执行c:\aa.bat而且结束时自动Close
所有程式如下:
PrivateDeclareFunctionOpenProcessLib"kernel32"_
(ByValdwDesiredAccessAsLong,ByValbInheritHandleAsLong,_
ByValdwProcessIdAsLong)AsLong
PrivateDeclareFunctionWaitForSingleObjectLib"kernel32"_
(ByValhHandleAsLong,ByValdwMillisecondsAsLong)AsLong
PrivateDeclareFunctionCloseHandleLib"kernel32"_
(ByValhObjectAsLong)AsLong
PrivateDeclareFunctionGetExitCodeProcessLib"kernel32"_
(ByValhProcessAsLong,lpExitCodeAsLong)AsLong
PrivateDeclareFunctionTerminateProcessLib"kernel32"_
(ByValhProcessAsLong,ByValuExitCodeAsLong)AsLong
PrivateDeclareFunctionGetForegroundWindowLib"user32"()AsLong
PrivateDeclareFunctionIsWindowLib"user32"_
(ByValhwndAsLong)AsLong

ConstPROCESS_QUERY_INFORMATION=&H400
ConstSTILL_ALIVE=&H103
ConstINFINITE=&HFFFF

PrivateExitCodeAsLong
PrivatehProcessAsLong
PrivateisDoneAsLong
PrivateSubCommand1_Click()
DimpidAsLong
pid=Shell("C:\tools\spe3\pe2.exe",vbNormalFocus)
hProcess=OpenProcess(PROCESS_QUERY_INFORMATION,0,pid)
isDone=False
Do
CallGetExitCodeProcess(hProcess,ExitCode)
Debug.PrintExitCode
DoEvents
LoopWhileExitCode=STILL_ALIVE
CallCloseHandle(hProcess)
isDone=True
EndSub

PrivateSubCommand2_Click()
DimpidAsLong
DimExitEventAsLong
pid=Shell("C:\tools\spe3\pe2.exe",vbNormalFocus)
hProcess=OpenProcess(PROCESS_QUERY_INFORMATION,0,pid)
ExitEvent=WaitForSingleObject(hProcess,INFINITE)
CallCloseHandle(hProcess)
EndSub

PrivateSubCommand3_Click()
DimaaAsLong
IfhProcess<>0Then
aa=TerminateProcess(hProcess,3838)
EndIf

EndSub

PrivateSubCommand4_Click()
DimpidAsLong
Dimhwnd5AsLong
pid=Shell("c:\tools\spe3\pe2.exe",vbNormalFocus)
hwnd5=GetForegroundWindow()
isDone=False
DoWhileIsWindow(hwnd5)
DoEvents
Loop
isDone=True
EndSub

PrivateSubCommand5_Click()
DimpidAsLong
'pid=Shell("c:\windows\command\xcopyc:\aa.bata:",vbHide)
pid=Shell("c:\command.com/cc:\aa.bat",vbNormalFocus)
EndSub->

上一篇:如何使用文件复制对话框 人气:3451
下一篇:ADO设定独占性的资料库 人气:2835
浏览全部Visual Basic的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐