如何在执行VB6中的其他代码之前等待shell进程完成 [英] How to wait for a shell process to finish before executing further code in VB6

查看:180
本文介绍了如何在执行VB6中的其他代码之前等待shell进程完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个小型VB6应用程序,在其中使用Shell命令执行程序.我将程序的输出存储在文件中.然后,我正在读取此文件,并使用VB6中的msgbox将输出显示在屏幕上.

I have a small VB6 app in which I use the Shell command to execute a program. I am storing the output of the program in a file. I am then reading this file and putting the output on the screen using a msgbox in VB6.

这是我的代码现在的样子:

This is what my code looks like now:

sCommand = "\evaluate.exe<test.txt "
Shell ("cmd.exe /c" & App.Path & sCommand)

MsgBox Text2String(App.Path & "\experiments\" & genname & "\freq")

问题是VB程序正在使用msgbox打印的输出是文件的旧状态.有什么方法可以保持VB代码的执行,直到我的shell命令程序完成,以便获得输出文件的正确状态而不是先前的状态?

The problem is that the output which the VB program is printing using the msgbox is the old state of the file. Is there some way to hold the execution of the VB code until my shell command program finishes so that I get the correct state of the output file and not a previous state?

推荐答案

执行此操作所需的秘诀是

The secret sauce needed to do this is the WaitForSingleObject function, which blocks execution of your application's process until the specified process completes (or times out). It's part of the Windows API, easily called from a VB 6 application after adding the appropriate declaration to your code.

该声明看起来像这样:

Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle _
                            As Long, ByVal dwMilliseconds As Long) As Long

它有两个参数:要等待的进程的句柄,以及表示要等待的最大时间的超时间隔(以毫秒为单位).如果您未指定超时间隔(值为零),则该函数将不等待并立即返回.如果指定了无限超时间隔,则当进程发出已完成信号时,该函数仅返回 .

It takes two parameters: a handle to the process that you want to wait on, and the time-out interval (in milliseconds) that indicates the maximum amount of time that you want to wait. If you do not specify a time-out interval (a value of zero), the function does not wait and returns immediately. If you specify an infinite time-out interval, the function returns only when the process signals that it has completed.

有了这些知识,剩下的唯一任务就是弄清楚如何对您启动的过程进行处理.事实证明这很简单,并且可以通过许多不同的方式来实现:

Armed with that knowledge, the only task that remains is figuring out how to get a handle to the process that you started. That turns out to be pretty simple, and can be accomplished a number of different ways:

  1. 一种可能性(以及我的处理方式)是使用

  1. One possibility (and the way I'd do it) is by using the ShellExecuteEx function, also from the Windows API, as a drop-in replacement for the Shell function that is built into VB 6. This version is far more versatile and powerful, yet just as easily called using the appropriate declaration.

它返回其创建的进程的句柄.您要做的就是将该句柄作为hHandle参数传递给WaitForSingleObject函数,您就可以开展业务了.在您调用的进程终止之前,应用程序的执行将被阻止(暂停).

It returns a handle to the process that it creates. All you have to do is pass that handle to the WaitForSingleObject function as the hHandle parameter, and you're in business. Execution of your application will be blocked (suspended) until the process that you've called terminates.

另一种可能性是使用 CreateProcess函数(再次,从Windows API中).此函数在与调用进程(即您的VB 6应用程序)相同的安全性上下文中创建一个新进程及其主线程.

Another possibility is to use the CreateProcess function (once again, from the Windows API). This function creates a new process and its primary thread in the same security context as the calling process (i.e., your VB 6 application).

Microsoft已发布了一个知识库文章,详细介绍了这种方法,甚至提供了完整的示例实现.您可以在此处找到该文章:如何使用32位应用程序确定Shelled进程何时结束.

Microsoft has published a knowledge base article detailing this approach that even provides a complete sample implementation. You can find that article here: How To Use a 32-Bit Application to Determine When a Shelled Process Ends.

最后,也许最简单的方法是利用内置Shell函数的返回值是应用程序任务ID的事实.这是一个唯一的数字,用于标识您启动的程序,并且可以将其传递给 OpenProcess函数获取可以传递给WaitForSingleObject函数的进程句柄.

Finally, perhaps the simplest approach yet is to take advantage of the fact that the built-in Shell function's return value is an application task ID. This is a unique number that identifies the program you started, and it can be passed to the OpenProcess function to obtain a process handle that can be passed to the WaitForSingleObject function.

但是,这种方法的简单性确实是有代价的.一个非常重要的缺点是,这将导致您的VB 6应用程序变得完全无响应.因为它将不会处理Windows消息,所以它将不会响应用户交互,甚至不会重绘屏幕.

However, the simplicity of this approach does come at a cost. A very significant disadvantage is that it will cause your VB 6 application to become completely unresponsive. Because it will not be processing Windows messages, it will not respond to user interaction or even redraw the screen.

VBnet 上的好伙伴在以下文章中提供了完整的示例代码: WaitForSingleObject:确定Shelled App何时结束.
我很希望能够在此处重现代码以帮助避免链接腐烂(VB 6现在已经出现了很多年;无法保证这些资源将永远存在),但是在发行许可证中代码本身似乎明确禁止这样做.

The good folks over at VBnet have made complete sample code available in the following article: WaitForSingleObject: Determine when a Shelled App has Ended.
I'd love to be able to reproduce the code here to help stave off link rot (VB 6 is getting up there in years now; there's no guarantee that these resources will be around forever), but the distribution license in the code itself appears to explicitly forbid that.

这篇关于如何在执行VB6中的其他代码之前等待shell进程完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆