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

查看:36
本文介绍了如何在 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 打印的输出是文件的旧状态.是否有某种方法可以在我的 shell 命令程序完成之前保持 VB 代码的执行,以便我获得输出文件的正确状态而不是以前的状态?

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?

推荐答案

做到这一点所需的秘诀是 WaitForSingleObject 函数,它会阻止应用程序进程的执行,直到指定进程完成(或超时).它是 Windows API 的一部分,可在向代码中添加适当的声明后轻松从 VB 6 应用程序调用.

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. 一种可能性(以及我的做法)是使用 ShellExecuteEx 函数,同样来自 Windows API,作为内置于 VB 6 中的 Shell 函数的替代品.这个版本是更加通用和强大,但使用适当的声明也很容易调用.

  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 位应用程序确定脱壳进程何时结束.

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:确定脱壳应用何时结束.
我希望能够在这里复制代码以帮助避免链接腐烂(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天全站免登陆