使用Shell指令具有Wait的功能

QQ1353695808

QQ1353695808

2016-02-19 14:24

给自己一点时间接受自己,爱自己,趁着下午茶的时间来学习图老师推荐的使用Shell指令具有Wait的功能,过去的都会过去,迎接崭新的开始,释放更美好的自己。
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:oolsspe3pe2.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:oolsspe3pe2.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:oolsspe3pe2.exe",vbNormalFocus)
  hwnd5=GetForegroundWindow()
  isDone=False
  DoWhileIsWindow(hwnd5)
  DoEvents
  Loop
  isDone=True
  
  
  
  而如何强迫shell所Create的process结束呢,那便是
  DimaaAsLong
  IfhProcess0Then
  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:oolsspe3pe2.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:oolsspe3pe2.exe",vbNormalFocus)
  hProcess=OpenProcess(PROCESS_QUERY_INFORMATION,0,pid)
  ExitEvent=WaitForSingleObject(hProcess,INFINITE)
  CallCloseHandle(hProcess)
  EndSub
  
  PrivateSubCommand3_Click()
  DimaaAsLong
  IfhProcess0Then
  aa=TerminateProcess(hProcess,3838)
  EndIf
  
  EndSub
  
  PrivateSubCommand4_Click()
  DimpidAsLong
  Dimhwnd5AsLong
  pid=Shell("c:oolsspe3pe2.exe",vbNormalFocus)
  hwnd5=GetForegroundWindow()
  isDone=False
  DoWhileIsWindow(hwnd5)
  DoEvents
  Loop
  isDone=True
  EndSub
  
  PrivateSubCommand5_Click()
  DimpidAsLong
  'pid=Shell("c:windowscommandxcopyc:aa.bata:",vbHide)
  pid=Shell("c:command.com/cc:aa.bat",vbNormalFocus)
  EndSub->

展开更多 50%)
分享

猜你喜欢

使用Shell指令具有Wait的功能

编程语言 网络编程
使用Shell指令具有Wait的功能

Linux系统Shell命令常用功能使用详解

服务器
Linux系统Shell命令常用功能使用详解

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

Java的wait(), notify()和notifyAll()使用心得

编程语言 网络编程
Java的wait(), notify()和notifyAll()使用心得

具有排毒功能的天然食品

生活常识 养生 健康
具有排毒功能的天然食品

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

Shell 编程

Linux Linux命令 Linux安装 Linux编程 Linux桌面 Linux软件 Linux内核 Linux管理
Shell 编程

VPS轻松控制Xen-Shell使用教程

服务器
VPS轻松控制Xen-Shell使用教程

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

固定电话开通黄钻不成功的原因及解决方法

固定电话开通黄钻不成功的原因及解决方法

检测磁盘类型的信息

检测磁盘类型的信息
下拉加载更多内容 ↓