Vb.net 如何在进程中的两个进程之间使用管道。开始

Vb.net 如何在进程中的两个进程之间使用管道。开始,vb.net,ffmpeg,pipeline,video-encoding,Vb.net,Ffmpeg,Pipeline,Video Encoding,我必须使用VB.NET运行此命令行: “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-预设5-x265参数级别=0:profile=未定义:pmode:no pme:pme:no high tier:ref=3:bframes=4:open gop:keyint=250:min keyint=25:b-adapt=2:bf

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

“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-预设5-x265参数级别=0:profile=未定义: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-pyram:me=hex:submi=2:merange=57:temporal mvp:weightp:no weightp:no weightp=2:no-rect:no-merge=2:no-weightb:no-rect:no-amp:vbv-bufsize=0:0:vbv-maxrate=0:vbv init=0:0.9:no-strict cbr:comp=0.6:qs=1:qs=1-强度=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无损:tu intra-depth=1:tu-inter-depth=1:tu-depth=1:强帧内平滑:无约束帧内:nr-intra=0:nr-inter=0:nr-inter=0:nr-inter=0:Blur=0=16 “H:\videotest\outputawdwd.mkv”

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

如果对vspipe使用普通进程声明,则会出现以下错误:

未知参数:|

在命令行中,脚本运行良好。我怀疑这意味着我必须手动在
vspipe
ffmpeg
之间进行管道传输

是否可以手动将输出从一个进程传送到另一个进程?我必须手动操作吗?

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

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
更新:

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

              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
然后我有一个backgroundworker(ConversionStats),它从字典中的每个进程获取stderr,并将它们打印到文本框中:

           '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获取streamreader的standarderror会导致获取字符串“无效句柄”。这是来自cmd stderr的错误,还是streamreader有问题

更新2

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

Microsoft Windows[Versione 6.3.9600] (c) 2013年微软公司。我是迪里蒂·瑞瑟瓦蒂

H:\Project\bin\Release>

本规范旨在澄清:

                Dim Proc As New Process

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

                'start process
                Proc.Start()

还有人可以指导我如何将STDOUTPUT从一个进程(vspipe.exe)通过管道/重定向到另一个进程(ffmpeg.exe)的STDIN?既然您知道您的命令字符串在命令行上工作,最简单的方法就是让
cmd.exe
为您运行代码。如中所述,Mark提供了一个如何在C#代码中实现这一点的示例

根据您的目的对其进行调整,并将其转换为VB.net可能如下所示(使用您在代码中声明的相同变量):

这与您之前所做的有何不同?您使用了
Process.Start
来运行
vspipe.exe
,然后将
参数传递给它。上面的新代码使用了
Process.Start
来代替运行
cmd.exe
,基本上打开了一个命令提示符窗口,并输入完整的命令行字符串

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

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

在这种特定情况下,问题在于
参数
字符串是一堆双引号,必须对其进行转义。在vb.net中,这是通过双双引号(
)完成的,如果双引号位于字符串的开头或结尾,则可以显示为“三重双引号”(
),如果有许多双引号需要转义,则可以显示为更长的倍数

虽然我的系统上没有测试所需的特定软件,但以下功能应该可以正常工作:

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()

请将您用于执行该行的代码添加到您的问题中。在命令窗口中输入该代码意味着操作系统正在处理arg,并且它知道如何使用管道。如果大部分代码是使用shell或Process作为arg传递给vspipe的。开始时,它可能不知道消息中所说的
是什么。那么,您该怎么做呢ou“run:那是从VB来的吗?好的,添加了我的VB.Net块。。我使用一个简单的进程启动,所以我的问题是如何在VB.NET中执行“|”?让操作系统来执行
StartInfo.FileName=“cmd”
然后将
executablepath
前置到
params
中,这样看起来就像在命令窗口中输入它一样
StartInfo.Arguments=params
然后启动进程我想从ffmpeg维护stderr,因为我需要为用户输出转换统计信息。。。有一种手动管道的方法吗?嗨,谢谢你的评论,问题是我必须获得ffmpeg标准。。如果我使用“cmd”,我可以获得没有问题的stderr吗?@ZedMachine-Yes;添加了示例。我想我会尝试一下;)非常感谢:)没办法让它工作。。。重定向的stdin stdout stderr进程已启动,但链接到进程的句柄(在调试模式下)不在任务管理器中。。当我尝试使用StreamReader使用.readnewline()时,它只是中断调试并在程序窗口中返回。。。。我刚刚尝试通过函数将参数传递给cmd,它工作得非常好!帮助我…请:)是的,我已经设法只杀死了相关的ffmpeg进程,以dame开始时间作为我的进程。所以我想现在结束了!!谢谢你刚才的回答;)
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()
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()