0

I am working with voice records. I need to use an .exe file for convert Wav to .mp3 file. Everything is fine I can execute this exe but I need to do something after when process end with my output .mp3 file. I know my output directory but i cant handle MP3 file before its not created yet. I know maybe I need to use Thread.sleep(); or something like that because I cant catch a file before its not exist.

Here is my code:

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

I was try to use process.WaitForExit();but I cant solve this problem. I still cant acces to mp3 file.

so how can I catch when the process finish?

Best Regards.

Mustafa Alan
  • 386
  • 3
  • 17
  • 1
    `process.WaitForExit();` should work. But you should also check whether lame.exe produces some error (i.e., fails to do the mp3 conversion for whatever reason). I don't know lame.exe, but see whether lame.exe returns exit codes ("errorlevel" values in batch files) in case of problems. Try checking the `Process.ExitCode` property after the process has exited (not before!). But first, check the Lame.exe documentation if and which exit codes it will provide. –  Oct 12 '18 at 15:49
  • Also, are you really sure Lame is being executed? Your code actually starts cmd.exe. Of course it will start cmd.exe just fine (i guess), but that is no proof that cmd.exe itself was able to run lame.exe. What i am trying to say here: Make sure that the path in the variable _extrasFilePath_ is actually the correct path to the lame.exe, and also make sure that you use correct and valid double-quoting for all the arguments you provide to cmd.exe (in a console window, type "cmd /?" to read detailed information about how to correctly quote) –  Oct 12 '18 at 15:51
  • 1
    Small correction to my first comment: `process.WaitForExit();` should work if you **remove** the `start` argument from your argument string. Sorry for not spotting this earlier. –  Oct 12 '18 at 15:54
  • Thanks for your advice. I am starting cmd.exe and my command is start another exe with correct parameters. It works fine . as I said i just need to catch when this process finish , and after I need to do something. `process.WaitForExit();` is working like "Wait. I need to do some stuff in process. Ahh! Okay. Its finished and now I can execute a new code line." ? @elgonzo – Mustafa Alan Oct 12 '18 at 16:00

2 Answers2

1

Remove the start command argument from your argument string and you should be able to use process.WaitForExit(); to wait for Lame to finish with encoding:

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


However, you can simplify your code and avoid this dance with cmd.exe altogether by starting lame.exe directly:

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



Below some information about why using the start command argument in your scenario is counterproductive.

Executing console applications such as lame.exe using cmd.exe (or from a console or batch file) normally block cmd.exe (or console/batch file) until the console application exits.

However, using the start command turns this normally blocking execution of a console application into a non-blocking execution. With this argument, the cmd.exe (or console/batch file) will continue execution while the console application is still running. In your particular case it means cmd.exe will exit right after it has started lame.exe (since it has nothing else to execute), effectively sabotaging your attempt to wait for lame.exe to finish.

-1

Edited:

Base on the comments below I have to make it clear that the oroginal solution I recommended does not check if the file is free but it checks only if the file exists! So I rather recommend the following:

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;
}

the usage will be:

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

ORIGINAL: You can use a while loop to find out when the file is ready:

while(!File.Exists(mp3FileName))
{
     //just wait
}
// add the attachment here
roozbeh S
  • 1,084
  • 1
  • 9
  • 16
  • No, you cannot use a while loop like that to find out when the file is "ready". The file is created (and thus exist) when lame.exe **starts** writing the file, not when it finishes with writing the file. The mere existence of the file is therefor no indicator of lame being finished with encoding/writing the mp3. –  Oct 12 '18 at 17:27
  • @elgonzo thanks for your tip, you are tight. However, I don't know about lame.exe but usually the file is written all at once when the conversion is done in memory. – roozbeh S Oct 12 '18 at 21:54
  • It is rather quite a stretch to assume a console application that takes an input file and writes the processed data into an output file does the data processing entirely in memory. Anyway, even if you would find a case where your assumption holds true, this approach is still unreliable. Even when the data is processed in memory and eventually written to a file "at once", writing the data to the file will take some time (which depends on the amount of data to be written and the performance characteristics of the underlying storage device/system). (1/2) –  Oct 13 '18 at 10:09
  • (2/2) Even in this scenario, the file already exists when the write operation starts, and not just when all data has been completely written to the file. The only situation in which your assumption is not in danger of failing badly is when the operation of writing the whole data to the file would require only a very,very miniscule amount of time (i.e., almost zero time). –  Oct 13 '18 at 10:12
  • You are right. I've done this with some apps that create `.csv` files as output and it always worked fine. Maybe for this case a Try-Catch block would be efficient. I will edit my answer based on this. – roozbeh S Oct 13 '18 at 10:17