【问题标题】:how to catch command prompt process finish in C# and do something after that?如何在 C# 中捕获命令提示符进程完成并在此之后执行某些操作?
【发布时间】:2018-10-12 15:36:21
【问题描述】:

我正在处理语音记录。我需要使用.exe 文件将Wav 转换为.mp3 文件。一切都很好,我可以执行这个 exe,但是当进程以我的输出 .mp3 文件结束后我需要做一些事情。我知道我的输出目录,但在尚未创建 MP3 文件之前我无法处理它。我知道也许我需要使用 Thread.sleep(); 或类似的东西,因为我无法在文件不存在之前捕获它。

这是我的代码:

string mp3GuidName = Guid.NewGuid().ToString();
var mp3FilePath = WavFilePath.Replace("finalWavFile", mp3GuidName).Replace("wav", "mp3");
var extrasFilePath = HttpContext.Current.Server.MapPath("/").Replace("DevApp.Web", "Extras");

string strArguments = "/c start " +  extrasFilePath + "lame.exe --abr 80 -V5 " + WavFilePath + " " + mp3FilePath;

System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "cmd.exe";
startInfo.Arguments =  strArguments ;
process.StartInfo = startInfo;
process.Start();
var attactment = new Attachment
    {
        CreatedOn = DateTime.Now,
        UpdatedOn = DateTime.Now,
        Title = mp3GuidName +".mp3",
        Size = _storageProvider.GetFile(mp3FilePath).GetSize(), // here I am trying to get mp3 file but i cant catch it. Because if this wav files size is huge, then convert process is taking time and my mp3 file is not created yet.
        FileExtension = _storageProvider.GetFile(mp3FilePath).GetFileType()
    };
attactment.MimeType = _storageProvider.GetMimeType(attactment.FileExtension);
attactment.FileUrl = mp3GuidName+".mp3";// file.GetName();
attactment.AttachmentFolderId = folder.Id;
_attachmentRepository.Add(attactment);

我尝试使用process.WaitForExit();,但我无法解决这个问题。我仍然无法访问 mp3 文件。

那么我怎样才能捕捉到这个过程何时结束?

最好的问候。

【问题讨论】:

  • process.WaitForExit(); 应该可以工作。但是您还应该检查 lame.exe 是否产生一些错误(即,无论出于何种原因,无法进行 mp3 转换)。我不知道 lame.exe,但看看 lame.exe 是否在出现问题时返回退出代码(批处理文件中的“错误级别”值)。在进程退出后(而不是之前!)尝试检查Process.ExitCode 属性。但首先,检查 Lame.exe 文档是否会提供退出代码以及它会提供哪些退出代码。
  • 另外,你真的确定 Lame 正在被处决吗?您的代码实际上启动了 cmd.exe。当然它会很好地启动 cmd.exe(我猜),但这并不能证明 cmd.exe 本身能够运行 lame.exe。我在这里想说的是:确保变量 extrasFilePath 中的路径实际上是 lame.exe 的正确路径,并确保对所有人使用正确且有效的双引号您提供给 cmd.exe 的参数(在控制台窗口中,键入“cmd /?”以阅读有关如何正确引用的详细信息)
  • 对我的第一条评论的小修正:如果您从参数字符串中删除 start 参数,process.WaitForExit(); 应该可以工作。很抱歉没有早点发现。
  • 感谢您的建议。我正在启动 cmd.exe,我的命令是用正确的参数启动另一个 exe。它工作正常。正如我所说,我只需要抓住这个过程完成的时间,以及在我需要做某事之后。 process.WaitForExit(); 的工作方式类似于“等等。我需要在处理过程中做一些事情。啊!好的。它完成了,现在我可以执行新的代码行了。” ? @elgonzo

标签: c# cmd process lame


【解决方案1】:

从您的参数字符串中删除start 命令参数,您应该能够使用process.WaitForExit(); 等待Lame 完成编码:

string strArguments = "/c " +  extrasFilePath + "lame.exe --abr 80 -V5 " + WavFilePath + " " + mp3FilePath;


但是,您可以通过直接启动 lame.exe 来简化代码并完全避免与 cmd.exe 发生这种关系:

string strArguments = "--abr 80 -V5 " + WavFilePath + " " + mp3FilePath;
...
startInfo.FileName = extrasFilePath + "lame.exe";
startInfo.Arguments = strArguments;
...



下面是一些关于为什么在你的场景中使用start 命令参数会适得其反的信息。

使用 cmd.exe(或从控制台或批处理文件)执行控制台应用程序(例如 lame.exe)通常会阻止 cmd.exe(或控制台/批处理文件),直到控制台应用程序退出。

但是,使用start 命令会将控制台应用程序的正常阻塞执行转变为非阻塞执行。使用此参数,cmd.exe(或控制台/批处理文件)将在控制台应用程序仍在运行时继续执行。在您的特定情况下,这意味着 cmd.exe 将在启动 lame.exe 后立即退出(因为它没有其他要执行的内容),从而有效地破坏了您等待 lame.exe 完成的尝试。

【讨论】:

    【解决方案2】:

    已编辑:

    根据下面的 cmets,我必须明确指出,我推荐的原始解决方案不会检查文件是否免费,而是仅检查文件是否存在 ! 所以我宁愿推荐以下:

    private bool IsBusy(FileInfo file)
    {
        FileStream stream = null;
    
        try
        {
            stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
        }
        catch ()
        {
            return true;
        }
        finally
        {
            if (stream != null)
                stream.Close();
        }
        return false;
    }
    

    用法如下:

    while(IsBusy(fileinfo))
    {
         //just wait
    }
    

    原文: 您可以使用 while 循环来确定文件何时准备就绪:

    while(!File.Exists(mp3FileName))
    {
         //just wait
    }
    // add the attachment here
    

    【讨论】:

    • 不,您不能使用这样的 while 循环来确定文件何时“准备就绪”。该文件是在 lame.exe 开始 写入文件时创建(并因此存在),而不是在它完成写入文件时创建。文件的存在并没有表明 mp3 的编码/编写完成了蹩脚的迹象。
    • @elgonzo 感谢您的提示,您很紧张。但是,我不知道 lame.exe,但通常当转换在内存中完成时,文件会一次全部写入。
    • 假设一个控制台应用程序接受输入文件并将处理后的数据写入输出文件,完全在内存中进行数据处理,这是相当牵强的。无论如何,即使您发现您的假设成立的情况,这种方法仍然不可靠。即使数据在内存中处理并最终“一次”写入文件,将数据写入文件也需要一些时间(这取决于要写入的数据量和底层存储设备的性能特征/系统)。 (1/2)
    • (2/2) 即使在这种情况下,文件在写入操作开始时已经存在,而不仅仅是在所有数据都已完全写入文件时。您的假设不会有严重失败的危险的唯一情况是,将整个数据写入文件的操作只需要非常非常少的时间(即几乎为零时间)。
    • 你是对的。我已经使用一些创建.csv 文件作为输出的应用程序完成了此操作,并且它始终运行良好。也许对于这种情况,Try-Catch 块会很有效。我将根据此编辑我的答案。
    猜你喜欢
    • 2021-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-26
    • 2020-08-06
    • 1970-01-01
    相关资源
    最近更新 更多