VB6里用CMD管道或SHELL命令去执行外部的EXE程序,这个EXE程序调用一个资源包,当我在VB6程序里执行这个EXE的时候,整个VB6窗体 就出现卡死状态,等外部EXE初始化这个资源包以后,程序才回答正常响应状态,提示执行完毕!其他中间过程根本无法和用户交互!当然如果这个资源包比较 小,比如只有1M以内,那么很快程序就能反映过来,大到几M以后,就总有一个卡死状态,试过了加doevents转让控制权,可是程序依然会卡死!不知道 这种情况下,如何防止其假死,其他比如VC或。NET都可以用多进程,但是VB6里好象即使用了多进程也不稳定,不知道该如何解决这种情况,非常感谢!

解决方案 »

  1.   

    SHELL 缺省是异步执行,出现这种情况,可能有二
    1、你是不是加了什么同步Shell的代码?
    2、你调用的外部程序本身,可能就很霸道,这种程序,不用VB调用,就是正常双击执行,也会让整个系统半天没响应?
      

  2.   

      谢了,这个外部exe没有图形界面的,直接双击无法执行,是个只能在XP/2000的CMD窗口执行的exe!
      那1的可能性比较大,但是我不知道你所说的同步shell是何意思,那代码该如何修改呢?
      我用的执行命令代码如下:
       Public Function ExecuteCommand(CommandLine As String) As String
    '管道方式执行DOS命令并返回执行结果
        Const BuffSize As Long = 1024
        Dim proc As PROCESS_INFORMATION
        Dim Ret As Long
        Dim start As STARTUPINFO
        Dim sa As SECURITY_ATTRIBUTES
        Dim hReadPipe As Long, hWritePipe As Long, lngBytesread As Long
        Dim strBuff As String * BuffSize, mOutputs As String
       
        sa.nLength = Len(sa)
        sa.bInheritHandle = 1&
        sa.lpSecurityDescriptor = 0&
        Ret = CreatePipe(hReadPipe, hWritePipe, sa, 0)
       
        If Ret = 0 Then ExecuteCommand = "CreatePipe Failed. Error: " & Err.LastDllError & vbCrLf: Exit Function
       
        start.cb = Len(start)
        start.dwFlags = &H100 Or 1
        start.hStdOutput = hWritePipe
        start.hStdError = hWritePipe
        Ret& = CreateProcessA(0&, CommandLine, sa, sa, 1, &H20, 0, 0, start, proc)
        If Ret <> 1 Then ExecuteCommand = "错误: '" & CommandLine & "' 不是可运行的程序" & vbCrLf: Exit Function
        Ret = CloseHandle(hWritePipe)    mOutputs = ""
        Do
            Ret = ReadFile(hReadPipe, strBuff, BuffSize, lngBytesread, 0&)
            If Ret = 0 Then Exit Do
            mOutputs = mOutputs & LeftB(StrConv(strBuff, vbFromUnicode), lngBytesread)
        Loop
       
        Ret = CloseHandle(proc.hProcess)
        Ret = CloseHandle(proc.hThread)
        Ret = CloseHandle(hReadPipe)
       
        ExecuteCommand = Replace(StrConv(mOutputs, vbUnicode), Chr(0), "")
    End Function
      

  3.   

    本帖最后由 bcrun 于 2011-01-04 10:16:20 编辑
      

  4.   

    本帖最后由 bcrun 于 2011-01-04 10:17:38 编辑
      

  5.   

    本帖最后由 bcrun 于 2011-01-04 10:18:01 编辑
      

  6.   

    这哪是shell,原来是用匿名管道进行父子进程通讯,这就不好说了,要看你的子进程的具体运行机制。
    管道本身就是同步机制,子进程写管道,必须等写完内容才能返回,父进程读也是这样,必须等子进程关闭全部写Handle,才会返回0
    子进程不主动关闭写Handle,父进程将一直挂着,就是假死。
    这种情况DoEvents,肯定没用,因为它是在Api调用中挂起的,根本不会执行其它语句。
    要解决问题,估计只有修改那个外部exe。
      

  7.   

        老大,谢了,那个外部exe是国际顶级大师的作品,我如果能修改,我就不用在这发贴了!哎,时间已经凌晨3点了,我依然没有想到好办法!
      

  8.   

      谢了,CMD管道方式至少还能执行命令,但是ShellExecute这个方法连外部命令都无法执行,无任何反映,加过路径或者不加路径,试了各种执行路径都无任何反映,我个人猜测你这个方法如果执行有图形界面的32位exe还行,如果执行只能在XPCMD窗口运行的EXE估计根本执行不了!
      

  9.   

         谢谢各位,我自己想出来了,只要用普通的shell命令就可以了,虽然shell方式的执行速度比CMD管道慢很多,但是它至少不会让VB6程序卡死,至于为什么,大家可以调用一些大型资源包进行一下测试即可,经过了8个晚上的通宵,进行着反复思考和测试,从一个对VB6几乎一无所知,到现在头发都快白了几根,终于让我想出整套方法了,几多欢喜几多愁,感叹一声,时间也不早了,凌晨3点30了。今天终于能睡得塌实些了,再次感谢各位!
      

  10.   

         呵呵,简单问题搞得那么复杂,直接普通方式就可以了,我不大会说理论知识,但是你用CMD管道不卡才怪!说通熟些,也许原理不是这样,但是实际证明确实如此,你用管道耗的是VB6程序,而你用普通方式,执行卡不卡就在于你的系统机器配置了,现在一般人的机器性能绝对不是问题。楼主以后这种问题自己多测试下就OK了。根本没必要提出来问,这又不是学术讨论的问题,这种问题直接GOOGLE就好了,我5年前就跟别人讨论过这种问题了。
      

  11.   

    那你用另一个线程吧.把工程属性改为ActiveX EXE,启动对象改为Sub Main,添加一些同步方面的代码(参考:如何在VB6里面实现稳定的多线程)然后直接把你这个过程用一个类封装一下,使用CreateObject创建,再调用之.....