注册 登录
编程论坛 VFP论坛

如何等待ShellExecute启动的程序运行结束再运行后面的代码

radiofan 发布于 2021-09-26 10:54, 2234 次点击
oApp = CREATEOBJECT("Shell.Application")
oApp.ShellExecute("test.exe",000, "", "", 1)  
等待test.exe运行结束 ……
messagebox("test.exe运行结束")
6 回复
#2
吹水佬2021-09-26 12:05
调用ShellExecute启动一个进程,相对调用进程来说是异步调用,不会阻塞。
如需要同步,可试试用WaitForSingleObject等待这个进程结束。
#3
radiofan2021-09-26 12:59
以下是引用吹水佬在2021-9-26 12:05:22的发言:

调用ShellExecute启动一个进程,相对调用进程来说是异步调用,不会阻塞。
如需要同步,可试试用WaitForSingleObject等待这个进程结束。


咋用
#4
吹水佬2021-09-26 16:22
回复 3楼 radiofan
调用API自定义几个函数参考
程序代码:
#DEFINE INFINITE                     -1
#DEFINE SEE_MASK_NOCLOSEPROCESS      0x00000040    && 使用hProcess成员
#DEFINE SEE_MASK_NOZONECHECKS        0x00800000    && 不检查,禁止安全警告
#DEFINE SEE_MASK_CONNECTNETDRV       0x00000080    && 验证共享和连接到驱动器
#DEFINE SEE_MASK_FLAG_NO_UI          0x00000400    && 不显示错误消息框
#DEFINE SW_SHOWNORMAL                1
#DEFINE STILL_ACTIVE                 0x00000103

DECLARE LONG StrDup IN Shlwapi STRING@
DECLARE LONG ShellExecuteEx IN Shell32 STRING@
DECLARE LONG WaitForSingleObject IN Kernel32 LONG, LONG
DECLARE LONG GetExitCodeProcess IN Kernel32 LONG, LONG@
DECLARE LONG CloseHandle IN Kernel32 LONG

**
** myExecuteEx(cFileName, cParameters)
** 运行一个外部程序(同步)
** cFileName ... in,  进程执行文件名(全路径)
** cParameters . in   程序的参数
**
FUNCTION myExecuteEx(cFileName, cParameters )
    LOCAL hProcess
    hProcess = 0
    IF myShellExecuteEx(cFileName,cParameters,@hProcess) AND hProcess>0
        * WaitForSingleObject(hProcess, INFINITE)
        * 用 WaitForSingleObject() 等待打开的外部进程结束
        * 问题: 外部进程卡死(无响应)问题
        * 试用 GetExitCodeProcess() 检测打开的外部进程是否结束
        myWaitForSingleObject(hProcess)
        CloseHandle(hProcess)
    ENDIF   
ENDFUNC

**
** myShellExecuteEx(cFileName, cParameters, hProcess)
** 运行一个外部程序
** cFileName ... in,  进程执行文件名
** cParameters . in   程序的参数
** hProcess .... out, 进程句柄
**
FUNCTION myShellExecuteEx(cFileName, cParameters, hProcess)
    LOCAL sei, nMask, hInstApp, cMsg
    nMask = SEE_MASK_NOCLOSEPROCESS;
          + SEE_MASK_FLAG_NO_UI;
          + SEE_MASK_CONNECTNETDRV;
          + SEE_MASK_NOZONECHECKS

        * SHELLEXECUTEINFO 结构
    sei = BINTOC(60, "4RS");
        + BINTOC(nMask, "4RS") + REPLICATE(0h00, 8);
        + BINTOC(StrDup(@cFileName), "4RS");
        + BINTOC(StrDup(@cParameters), "4RS") + REPLICATE(0h00, 4);
        + BINTOC(SW_SHOWNORMAL, "4RS") + REPLICATE(0h00, 28)
         
    IF ShellExecuteEx(@sei) == 0
        hInstApp = CTOBIN(SUBSTR(sei,33,4), "4RS")
        cMsg = ICASE(hInstApp == 2,  "没有找到文件",;
                     hInstApp == 3,  "没有找到路径",;
                     hInstApp == 5,  "拒绝访问",;
                     hInstApp == 8,  "内存不足",;
                     hInstApp == 32, "没有找到动态链接库",;
                     hInstApp == 26, "不能操作一个以打开的文件",;
                     hInstApp == 27, "文件关联信息不完整",;
                     hInstApp == 28, "DDE操作超时",;
                     hInstApp == 29, "DDE操作失败",;
                     hInstApp == 30, "DDE繁忙",;
                     hInstApp == 31, "没有找到文件关联", "未知错误")
        MESSAGEBOX("运行 " + cFileName + " 异常:" + cMsg, "提示")
        RETURN .F.
    ENDIF
    hProcess = CTOBIN(SUBSTR(sei,57,4), "4RS")
    RETURN .T.
ENDFUNC

FUNCTION myWaitForSingleObject(hProcess)
    LOCAL nExitCode
    * GetExitCodeProcess() 检测打开的外部进程是否结束
    nExitCode = 0
    DO WHILE GetExitCodeProcess(hProcess,@nExitCode)!=0 AND nExitCode==STILL_ACTIVE
        DOEVENTS
        INKEY(0.5)
    ENDDO
ENDFUNC

#5
schtg2021-09-26 18:33
学习啦,谢谢吹版分享!
#6
radiofan2021-09-26 18:45
回复 4楼 吹水佬
谢谢吹版,恕我偷懒 …… 慢慢消化!
#7
radiofan2021-11-05 09:17
单纯运行,不传递参数,用这个比较方便
obj = Createobject("WScript.Shell")
obj.Run('cmd /c 运行程序名',0,.T.),第三个参数可以控制是否等待
1