WScript.Shell.Exec子进程stdout读取前的非阻塞检测问题
背景
我使用以下代码读取通过Wscript.Shell.Exec启动的进程的stdout:
Sub Main() Dim lspProcess As IWshExec = CreateObject("Wscript.Shell").Exec("deno lsp") Debug.Print readMessage(lspProcess) End Sub Function readMessage(lsp As IWshExec) As String Static contentLengthMatch As Object If contentLengthMatch Is Nothing Then Set contentLengthMatch = CreateObject("VBScript.RegExp") contentLengthMatch.IgnoreCase = True contentLengthMatch.Global = False contentLengthMatch.Pattern = "^Content-Length: (\d+)" 'contentLengthMatch.Compile End If With lsp.StdOut Dim header As String = .ReadLine() Debug.Assert contentLengthMatch.Test(header) 'PERF: use mid Debug.Assert .ReadLine() = vbNullString 'swallow extra newline, could use skipline without the assert Dim contentLength As Long = Int(contentLengthMatch.Execute(header)(0).SubMatches(0)) Return lsp.StdOut.Read(contentLength) End With End Function
如您所见,将进程(lsp As IWshExec)传入后,我的代码会查找特定格式的消息并返回读取到的字符串。该消息的头部格式如下:
Content-Length: 14 {"data":"foo"}
因此可以通过一次Read调用确定后续需要读取的数据量。
问题
当我在stdout无数据时误调用readMessage函数,问题就出现了。此时VBA会在第一个.ReadLine()处无限挂起,等待永远不会到来的数据,最终程序无响应甚至崩溃,且没有任何错误提示。
我尝试过多种检查方式:
Debug.Assert Not lsp.StdOut.AtEndOfStream Debug.Assert Not lsp.StdOut.AtEndOfLine Debug.Assert Not lsp.StdOut.Read(1) = vbNullString Debug.Assert lsp.Status = vbRunning 'always true
但似乎任何检查stdout的操作都会阻塞到有数据出现为止,进而导致父进程挂起。
内容的提问来源于stack exchange,提问作者Greedo
相关产品推荐
相关产品推荐

