首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Process.Start中使用两个进程之间的管道

如何在Process.Start中使用两个进程之间的管道
EN

Stack Overflow用户
提问于 2015-05-30 13:01:10
回答 1查看 3.4K关注 0票数 1

我必须使用VB.NET运行这个命令行:

"H:\videotest\test.vpy“- "H:\Release\data\bin64\ffmpeg.exe”-hwaccel汽车-y -i - -map 0:v:0 -c:v libx265 -crf 20.0 -preset 5 -x265-params -y -imerange=57:temporal-mvp:weightp:no-weightb:max-merge=2:no-weightb:no-rect:no-amp:vbv-bufsize=0:vbv-maxrate=0:vbv-init=0.9:no-strict-cbr:qcomp=0.6:qstep=4:aq-mode=1:aq-strength=1.0:cutree:no-early-skip:min-cu-size=8:ctu=64:no-fast-cfb:ipratio=1.4:pbratio=1.3:cbqpoffs=0:crqpoffs=0:rd=3:psy-rd=0.3:psy-rdoq=1:no-b-intra:no-fast-intra:rdoq-level=1:no-tskip:no-tskip-fast:cu-lossless:tu-intra-depth=1:tu-inter-depth=1:strong-intra-smoothing:no-constrained-intra:nr-intra=0:nr-inter=0:qblur=0.5:cplxblur=20:signhide:sar=16 "H:\videotest\outputawdwd.mkv“

vspipe.exe运行test.vpy脚本并将筛选器应用于视频输入或调整视频输入的大小,然后将输出通过管道传输到ffmpeg进行编码。

如果我使用带vspipe的正常进程声明,它会给出以下错误:

未知的论点:\x

在命令行中,脚本工作得很好。我怀疑这意味着我必须手动在vspipeffmpeg之间输送管道。

可以手动将输出从一个进程输送到另一个进程吗?我必须手动做吗?

下面是我启动流程的功能:

代码语言:javascript
复制
executablepath = "H:\Project\VapourSynth\core64\vspipe.exe"

params = "H:\videotest\test.vpy" - -y | "H:\Release\data\bin64\ffmpeg.exe" -hwaccel auto -y -i - -map 0:v:0 -c:v libx265 -crf 20.0 -preset 5 -x265-params level=0:profile=undefined:pmode:no-pme:pme:no-high-tier:ref=3:bframes=4:open-gop:keyint=250:min-keyint=25:b-adapt=2:bframe-bias=0:rc-lookahead=20:no-scenecut:b-pyramid:me=hex:subme=2:merange=57:temporal-mvp:weightp:no-weightb:max-merge=2:no-weightb:no-rect:no-amp:vbv-bufsize=0:vbv-maxrate=0:vbv-init=0.9:no-strict-cbr:qcomp=0.6:qstep=4:aq-mode=1:aq-strength=1.0:cutree:no-early-skip:min-cu-size=8:ctu=64:no-fast-cfb:ipratio=1.4:pbratio=1.3:cbqpoffs=0:crqpoffs=0:rd=3:psy-rd=0.3:psy-rdoq=1:no-b-intra:no-fast-intra:rdoq-level=1:no-tskip:no-tskip-fast:cu-lossless:tu-intra-depth=1:tu-inter-depth=1:strong-intra-smoothing:no-constrained-intra:nr-intra=0:nr-inter=0:qblur=0.5:cplxblur=20:signhide:sar=16 "H:\videotest\outputawdwd.mkv"

Private Sub CreateJobProcess(ByVal Name, ByVal executablepath, ByVal params)

    Try

        If Not jobs_processes.ContainsKey(Name) Then

            Dim Proc As New Process

            Proc.StartInfo.UseShellExecute = False
            Proc.StartInfo.CreateNoWindow = True
            Proc.StartInfo.RedirectStandardError = True
            Proc.StartInfo.FileName = "" & executablepath & ""
            Proc.StartInfo.Arguments = params

            'start process
            Proc.Start()

            'add new process to dictionary
            jobs_processes.Add(Name, Proc)

            'TEMP
            My.Settings.giobbe -= 1

            'start background workers for statistics
            If Not ConversionStats.IsBusy Then
                ConversionStats.WorkerSupportsCancellation = True
                ConversionStats.RunWorkerAsync()
            End If

            If Not UpdateListJob.IsBusy Then
                UpdateListJob.WorkerSupportsCancellation = True
                UpdateListJob.RunWorkerAsync()
            End If

        End If

    Catch ex As Exception
        Me.Invoke(New MethodInvoker(Sub() Logbox.AppendText(Environment.NewLine & ">Program exception:" & Environment.NewLine & ex.Message & Environment.NewLine)))
        MsgBox(ex.Message)
    End Try
End Sub

更新:

这是我更改的块,这个函数为需要创建的作业获取作业名称和参数,然后将该过程保存在字典中。

代码语言:javascript
复制
              Dim Proc As New Process

                Proc.StartInfo.UseShellExecute = False
                Proc.StartInfo.CreateNoWindow = True
                Proc.StartInfo.RedirectStandardError = True
                Proc.StartInfo.FileName = "cmd"
                Proc.StartInfo.Arguments = params

                'start process
                Proc.Start()

                'add new process to dictionary
                jobs_processes.Add(Name, Proc)

                'TEMP
                My.Settings.giobbe -= 1

                'start background workers for statistics
                If Not ConversionStats.IsBusy Then
                    ConversionStats.WorkerSupportsCancellation = True
                    ConversionStats.RunWorkerAsync()
                End If

                If Not UpdateListJob.IsBusy Then
                    UpdateListJob.WorkerSupportsCancellation = True
                    UpdateListJob.RunWorkerAsync()
                End If

然后我有一个背景工作者( ConversionStats ),它从字典中的每个进程获取stderr,并将它们打印到文本框中:

代码语言:javascript
复制
           'take current selected process and set streamreader
            Dim tmpproc As Process = jobs_processes(CurrentJob)
            Dim ffmpeg_stats As StreamReader
            Dim stdoutput As String = ""

            'something that verify if the job is started 

            If statejob = 1 Then    'if job is working

                'take stderr from ffmpeg
                ffmpeg_stats = tmpproc.StandardError
                stdoutput = ffmpeg_stats.ReadLine()

                If stdoutput IsNot Nothing Then 'if ffmpeg stderr is not nothing 

                    'IF FFMPEG IS RETURNING STATS
                    If stdoutput.Contains("frame=") Or stdoutput.Contains("size=") Then

这是我的密码..。但是现在,随着cmd的标准化,流读取器产生了一个字符串“无效句柄”。这是cmd stderr的错误,还是流读取器有问题?

更新2

我甚至尝试启动一个干净的cmd进程,只声明参数,但结果只是控制台上有主信息。

微软视窗Versione 6.3.9600 2013微软公司。图蒂·迪里蒂·里萨瓦蒂。

H:\Project\bin\Release>

这是要澄清的守则:

代码语言:javascript
复制
                Dim Proc As New Process

                Proc.StartInfo.FileName = "cmd"
                Proc.StartInfo.Arguments = params

                'start process
                Proc.Start()

还有人可以指导我如何将STDOUTPUT从一个进程(vspipe.exe)引导到另一个进程的STDIN (ffmpeg.exe)?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-30 23:17:57

因为您知道命令字符串在命令行上工作,所以最简单的方法就是让cmd.exe为您运行代码。正如Plutonix在他的评论中所建议的那样,在这个答案中,Mark提供了一个如何在C#代码中这样做的示例。

代码语言:javascript
复制
Process test = new Process();
test.StartInfo.FileName = "cmd";
test.StartInfo.Arguments = @"/C ""echo testing | grep test""";
test.Start();

使其适应您的目的,并将其转换为VB.net可能类似于这样(使用您在代码中声明的相同变量):

代码语言:javascript
复制
Dim Proc As New Process()
Proc.StartInfo.FileName = "cmd"
Proc.StartInfo.Arguments = "/C """ & executablepath & " " & params & """
Proc.Start()

这和你以前做的有什么不同?您使用Process.Start运行vspipe.exe,然后将其传递给您的params。上面的新代码使用Process.Start来代替运行cmd.exe,本质上打开一个命令提示符窗口,并输入完整的命令行字符串。

接收stdoutstderr需要两个步骤。首先,必须将每个属性的“重定向”属性设置为True,然后在启动流程后,手动检索所需的输出。

代码语言:javascript
复制
Dim Proc As New Process()
Proc.StartInfo.FileName = "cmd"
Proc.StartInfo.Arguments = executablepath & " " & params

'Capture stdio & stderr:
Proc.StartInfo.RedirectStandardOutput = True
Proc.StartInfo.RedirectStandardError = True

Proc.Start()

'Read stdio & stderr:
Dim StdIO As String = Proc.StandardOutput.ReadToEnd()
Dim StdErr As String = Proc.StandardError.ReadToEnd()

RE:更新2

这种特殊情况下的问题是,Arguments字符串是一堆双引号,必须转义。在vb.net中,这是用双引号("")完成的,如果双引号位于字符串的开头或结尾,就可以显示为“三重双引号”("""),如果需要转义的话,双引号的倍数甚至更长。

尽管我的系统上没有测试所需的特定软件,但以下几点应该可以工作:

代码语言:javascript
复制
Dim Proc As New Process
Proc.StartInfo.CreateNoWindow = True
Proc.StartInfo.UseShellExecute = False
Proc.StartInfo.FileName = "cmd"
Proc.StartInfo.Arguments = "/C ""H:\Project\VapourSynth\core64\vspipe.exe ""H:\videotest\test.vpy"" - -y | ""H:\Release\data\bin64\ffmpeg.exe"" -hwaccel auto -y -i - -map 0:v:0 -c:v libx265 -crf 20.0 -preset 5 -x265-params level=0:profile=undefined:pmode:no-pme:pme:no-high-tier:ref=3:bframes=4:open-gop:keyint=250:min-keyint=25:b-adapt=2:bframe-bias=0:rc-lookahead=20:no-scenecut:b-pyramid:me=hex:subme=2:merange=57:temporal-mvp:weightp:no-weightb:max-merge=2:no-weightb:no-rect:no-amp:vbv-bufsize=0:vbv-maxrate=0:vbv-init=0.9:no-strict-cbr:qcomp=0.6:qstep=4:aq-mode=1:aq-strength=1.0:cutree:no-early-skip:min-cu-size=8:ctu=64:no-fast-cfb:ipratio=1.4:pbratio=1.3:cbqpoffs=0:crqpoffs=0:rd=3:psy-rd=0.3:psy-rdoq=1:no-b-intra:no-fast-intra:rdoq-level=1:no-tskip:no-tskip-fast:cu-lossless:tu-intra-depth=1:tu-inter-depth=1:strong-intra-smoothing:no-constrained-intra:nr-intra=0:nr-inter=0:qblur=0.5:cplxblur=20:signhide:sar=16 ""H:\videotest\outputawdwd.mkv"""
Proc.StartInfo.RedirectStandardOutput = True
Proc.StartInfo.RedirectStandardError = True

Proc.Start()
Dim so As String = Proc.StandardOutput.ReadToEnd
Dim se As String = Proc.StandardError.ReadToEnd
Proc.WaitForExit()
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30546522

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档