I'm currently busy with a small C# application that reads a folder then dynamically lists all .rar files on a windows form with a dynamic progress bar next to each .rar file. So basically with the press of a button, the .rar files needs to be unzipped (winrar command line) showing the progress for each process.
Below is my process snippet
Process proc = new Process();
proc.StartInfo.FileName = #"unrar.exe";
proc.StartInfo.Arguments = FileName + "whatever attributes/switches";
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardInput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.OutputDataReceived += new DataReceivedEventHandler(proc_OutputDataReceived);
proc.Start();
proc.BeginOutputReadLine();
proc.WaitForExit();
Having trouble getting this right.
Help will be much appreciated.
If unrar.exe outputs the progress to the standard output, you could try and parse it to update the progressbar.
Instead of using unrar.exe to uncompress the archives from within your program, you could try using a library, like SevenZipLib http://sevenziplib.codeplex.com/.
The problem may be that UNRAR doesn't output a NewLine, and just keeps writing to the same line, so the event handler never gets called. It only gets called once a new line is written.
I would go with Simon's solution and try to use 7zip instead. It's more friendly has a great C# library and works with almost all formats.
Related
I created this simple .bat File:
mstsc C:\Temp\example.rdp
DEL C:\Temp\example.rdp
The normal behaviour of the .bat file is to open the rdp dialog and wait til I close the RDP connection. After that the .rdp file will be deleted.
This works perfect for me.
Now I want to open the .bat file from my C# WPF project with a click on a button.
Process p = new Process();
p.StartInfo.FileName = #"cmd.exe";
p.StartInfo.WorkingDirectory = #"C:\Temp";
p.StartInfo.Arguments = "/k " + "example.bat";
p.Start();
I tried all different arguments but the result is always the same the .bat file won't wait for the mstsc command to finish.
Do you have an idea to get this work?
Edit:
I want the .bat file because i want to delete the .rdp file although my program isn't running and i don't want to close all rdp connections when i close the program.
Why are you not directly running mstsc?
Process.Start("mstsc", "dir-to-blah.rdp").WaitForExit();
File.Delete("dir-to-blah.rdp");
try using the "start" command.
start is documented here: https://ss64.com/nt/start.html
you should be able to do something like
Process p = new Process();
p.StartInfo.FileName = #"cmd.exe";
p.StartInfo.WorkingDirectory = #"C:\Temp";
p.StartInfo.Arguments = "start /w" + "/k " + "example.bat";
p.Start();
(as usual, my code is completely untested - leaving the final solution up to the OP)
Trying to write a video compression app using Windows Forms, I can get the file to compress ok, but I'm looking to show the process to something like a textbox?
At the minute the program doesn't have a progress, so you don't know if its complete or not, is it possible to output with FFMPEG is doing to a textbox?
This is my code, when it runs nothing is shown in the textbox:
string ffmpeg = #"c:\test\ffmpeg.exe";
ProcessStartInfo psi = new ProcessStartInfo(ffmpeg);
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardOutput = true;
psi.Arguments = "-i c:\\test\\small.mp4 -s 480x272 c:\\test\\compressed.mp4";
var proc = Process.Start(psi);
string s = proc.StandardOutput.ReadToEnd();
textBox1.Text = s;
Do i need to pass something else into the ProcessStartInfo section?
You need to periodically check back with proc.StandardOutput to see if there is new text there. Right immediately after you've started the program, it's no surprise that it hasn't managed to write anything yet.
I'd advise using a Timer for that.
Why "1.bat" can't run successfully? Any help will be appreciate. "1.bat" was created successfully.It can run without error, but can't rename the files.
private void button1_Click(object sender, EventArgs e)
{
string str = System.Environment.CurrentDirectory;
str += "\\1.bat";
string txt = "";
txt = "ren *.mp3 *.wav";
StreamWriter sw = new StreamWriter(str,false, Encoding.UTF8);
sw.Write(txt);
sw.Close();
Process p = new Process();
p.StartInfo.FileName = str;
p.StartInfo.Arguments = "";
p.StartInfo.UseShellExecute = false;
p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
p.Start();
}
One problem is that your file is being written with a UTF-8 BOM. Try passing Encoding.Default to test this out. Or pass new UTF8Encoding(false) as the encoding to pass a UTF-8 encoding that omits the BOM.
Another problem (which you just added in an edit) is that you set UseShellExecute to false. That requires the file you pass to be an executable file. Your file isn't. You need UseShellExecute to be true to allow the shell to work out how to process your .bat file.
And yet another possible problem is that the current directory may not be what you think it is.
When faced with problems like this there is no need at all to be helpless. Do some debugging. Add a pause at the end of your batch file and make sure that you can see the console. You'll find out immediately what the problem is. Learning how to debug is just as important as learning how to program. You won't be able to do the latter until you can do the former.
If I were having to do it this way, with an external process, I would:
Set UseShellExecute to false.
Pass cmd.exe as the executable file.
Pass the command to be executed as the command line.
However, it would be much easier to do this directly using C# and so avoid having to spin up external processes.
I'm executing a batch file from my C# application using the System.Diagnostics classes, updating my GUI with the output along the way, but as soon as my batch file is in excess of a certain number of lines, the process just hangs. The exact amount of lines seems to vary, but I have been able to reproduce it with a simple batch file that prints "Hello Kitty" 316 times:
#echo off
echo Hello Kitty
echo Hello Kitty
etc.
If I remove the 316th line, the batch file executes fine and the forms application behaves as expected, but any more lines causes the process to suspend indefinitely, not producing even one of the first 300 hello kitties.
Here is my code for executing the batch file:
process = new System.Diagnostics.Process();
process.StartInfo.FileName = batchName;
process.StartInfo.Arguments = " < nul";
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.UseShellExecute = false;
process.Start();
with these declared elsewhere:
protected Process process;
protected StreamReader output;
My main form does something like this (simplified a little):
string output;
while (!proc.Process.HasExited)
{
proc.Process.WaitForExit(200);
if (proc.Process.HasExited)
{
output = proc.Output.ReadToEnd();
rtbStatus.AppendText(output);
}
Application.DoEvents();
}
I don't understand why it does this, and no examples that I find on the net make any mention of a size limit on batch files. Please advise.
You need to read the output continuously - you cannot wait to the end.
Output will be buffered, so a small amount (usually about 4KB) can be written before the process hangs.
The alternative is to direct the output to a file then read the file.
So anyways, I've been working on a batch IDE, and I was wondering if there was a good way to effectively embed the file into the form.
It would function sort of like a debug mode, where at any time, the user can click a button, and the batch file would load into the actual form.
Like the black cmd window would be embedded into the form...
Is there any way to do that?
ProcessStartInfo psi = new ProcessStartInfo();
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.FileName = "C:\\echo.cmd";
var p = Process.Start(psi);
Console.WriteLine(p.StandardOutput.ReadToEnd());
And in C:\echo.cmd I have just basic echo hello!. When this code is executed - you'll see hello! received from batch's output stream.
Note that if executed command will wait for some input - ReadToEnd() can't return. In this case you should use Process.OutputDataReceived event.
Look at the process object and the StandardInput, StandardOutput and StandardError streams.
That is essentially all the command window is showing with some special handling of control characters.