I tried using the Process class as always but that didn't work. All I am doing is trying to run a Python file like someone double clicked it.
Is it possible?
EDIT:
Sample code:
string pythonScript = #"C:\callme.py";
string workDir = System.IO.Path.GetDirectoryName ( pythonScript );
Process proc = new Process ( );
proc.StartInfo.WorkingDirectory = workDir;
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.FileName = pythonScript;
proc.StartInfo.Arguments = "1, 2, 3";
I don't get any error, but the script isn't run. When I run the script manually, I see the result.
Here's my code for executing a python script from C#, with a redirected standard input and output ( I pass info in via the standard input), copied from an example on the web somewhere. Python location is hard coded as you can see, can refactor.
private static string CallPython(string script, string pyArgs, string workingDirectory, string[] standardInput)
{
ProcessStartInfo startInfo;
Process process;
string ret = "";
try
{
startInfo = new ProcessStartInfo(#"c:\python25\python.exe");
startInfo.WorkingDirectory = workingDirectory;
if (pyArgs.Length != 0)
startInfo.Arguments = script + " " + pyArgs;
else
startInfo.Arguments = script;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardInput = true;
process = new Process();
process.StartInfo = startInfo;
process.Start();
// write to standard input
foreach (string si in standardInput)
{
process.StandardInput.WriteLine(si);
}
string s;
while ((s = process.StandardError.ReadLine()) != null)
{
ret += s;
throw new System.Exception(ret);
}
while ((s = process.StandardOutput.ReadLine()) != null)
{
ret += s;
}
return ret;
}
catch (System.Exception ex)
{
string problem = ex.Message;
return problem;
}
}
Process.Start should work. if it doesn't, would you post your code and the error you are getting?
You forgot proc.Start() at the end. The code you have should work if you call Start().
Related
I'am working with Process, and it has strange behavior. I need to execute code with Process my WebSections.exe program. Interesting thing, when i pass wrong parameters, it show result that it wrong, when i pass correct parameters it does not show anything, like it would not execute anything at all.
So parameters for my program is WebSections.exe f (.xml file).
But if i call with same parameters as in the code but straight out of command-line, it works.
And also i commented the .ExitCode, bacuse it shows: "System.Exception: Program returned with error code 2 at simplepage.". But with it commented it seems to be working.
Process p;
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "C:\\inetpub\\WebSections\\Program\\WebSections.exe";
psi.Arguments = "f C:\\Users\\HrchM\\Desktop\\Program\\Current_Diagram\\diagramResult.xml";
psi.WorkingDirectory = "C:\\inetpub\\WebSections\\TempFolder";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
p = Process.Start(psi);
try
{
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit(60000);
/* if (p.ExitCode != 0)// returns 255 when it can’t write to the temp folder (C:\inetpub\WebSections, CZ-CRM\IIS_IUSRS, Modify, replace all child objects)
throw new Exception("Program returned with error code " + p.ExitCode); */
ViewData["Content"] = output.ToString();
}
catch (Exception ex)
{
ViewData["Content"] = ex.ToString();
}
finally
{
p.Close();
p.Dispose();
}
The job of the method ExecuteCommandSync is to detect the silences from a video and return the output as string but when I run this code it never bring the value of proc.HasExited as true. If I forcefully drag the debugger to the line
result =proc.StandardOutput.ReadToEnd()
then it never exit the ffmpeg.exe so as a result control never returns back.
Although the same method is working fine for a different command like creating an audio file from a video. In this case proc.HasExited also returns false but it also generates the audio file successfully.
public static string ExecuteCommandSync(string fileName, int timeoutMilliseconds)
{
string result = String.Empty;
string workingDirectory = Directory.GetCurrentDirectory();
try
{
string command = string.Format("ffmpeg -i {0} -af silencedetect=noise=-20dB:d=0.2 -f null -", "\"" + fileName + "\"");
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
procStartInfo.WorkingDirectory = workingDirectory;
procStartInfo.RedirectStandardOutput = true;
procStartInfo.RedirectStandardError = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = false;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
proc.WaitForExit(timeoutMilliseconds);
// Get the output into a string
if (proc.HasExited)
{
if (!proc.StandardOutput.EndOfStream)
{
result = proc.StandardOutput.ReadToEnd();
}
else if (!proc.StandardError.EndOfStream)
{
result = "Error:: " + proc.StandardError.ReadToEnd();
}
}
}
catch (Exception)
{
throw;
}
return result;
}
So please advice.
I am getting the error:
Cannot access the file because it is being used by another process
I have a C# desktop app.
I am using the Process class to convert images to a video file by using FFMPEG.
This is my code:
using (Process serverBuild = new Process())
{
serverBuild.StartInfo.WorkingDirectory = Environment.CurrentDirectory;
string args = " -f image2 -i " + {path} + "\\img%05d.jpg -s 352x288 -filter:v \"setpts=5.0*PTS\" -y " + {path}\\File.mp4;
serverBuild.StartInfo.Arguments = args;
serverBuild.StartInfo.FileName = "ffmpeg.exe";
serverBuild.StartInfo.UseShellExecute = false;
serverBuild.StartInfo.RedirectStandardOutput = true;
serverBuild.StartInfo.RedirectStandardError = true;
serverBuild.StartInfo.CreateNoWindow = true;
serverBuild.Start();
// string output = serverBuild.StandardOutput.ReadToEnd();
//Log.Instance.Debug(serverBuild.StandardError.ReadToEnd());
serverBuild.WaitForExit();
serverBuild.Close();
}
Directory.Delete(ExportRoute + FFMPEGPacket.LicenseKey + "\\" + FFMPEGPacket.Guid, true);
//which raise the error..
The images are all deleted but the File.Mp4 is not and that is the error. The error says that the newly created MP4 file cannot be deleted.
NB
This is partial code to illustrate the error
You may try the following code to create the file (it worked for me):
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = exe_path;
// replace your arguments here
psi.Arguments = string.Format(#" arguments ")
psi.CreateNoWindow = true;
psi.ErrorDialog = true;
psi.UseShellExecute = false;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.RedirectStandardOutput = true;
psi.RedirectStandardInput = false;
psi.RedirectStandardError = true;
Process exeProcess = Process.Start(psi);
exeProcess.PriorityClass = ProcessPriorityClass.High;
string outString = string.Empty;
exeProcess.OutputDataReceived += (s, e) =>
{
outString += e.Data;
};
exeProcess.BeginOutputReadLine();
string errString = exeProcess.StandardError.ReadToEnd();
Trace.WriteLine(outString);
Trace.TraceError(errString);
exeProcess.WaitForExit();
exeProcess.Close();
exeProcess.Dispose();
FFMPEG might still be rendering the creation of video from images after it closes, so it might be worth if you place a Threading.Thead.Sleep(5000) 5 secs; before delete.
Try that:
File.WriteAllBytes(path, new byte[0]);
File.Delete(path);
I have a console application (Host.exe) that is written in Delphi. It accepts stdin readln and responses to stdout by writeln.
Now, I want to use Host.exe in C# application in a way that C# gives input to Host.exe and gets the output from Host.exe
Ideally, I write the code below but it doesn't work: it hangs somewhere in the outputReader.ReadLine();
System.IO.File.WriteAllText(tmp, vbs);
Process pProcess = new Process();
pProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
//strCommand is path and file name of command to run
pProcess.StartInfo.FileName = #"Host.exe";
pProcess.StartInfo.Arguments = "\"runa " + tmp +"\"";
// runs script file tmp in background
pProcess.StartInfo.CreateNoWindow = true;
pProcess.StartInfo.UseShellExecute = false;
pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.StartInfo.RedirectStandardInput = true;
pProcess.StartInfo.RedirectStandardError = true;
pProcess.Start();
StreamWriter inputWriter = pProcess.StandardInput;
StreamReader outputReader = pProcess.StandardOutput;
while (true)
{
inputWriter.WriteLine("getmsg");
inputWriter.Flush();
string s = outputReader.ReadLine(); // then do something with it
inputWriter.WriteLine("progressglobal");
inputWriter.Flush();
string p = outputReader.ReadLine();
if (p == "100")
{
break;
}
Application.DoEvents();
Thread.Sleep(1000);
}
inputWriter.WriteLine("exit");
inputWriter.Flush();
pProcess.WaitForExit();
Many thanks for any suggestions in advance !
You read the line twice:
string s = outputReader.ReadLine();
and
string p = outputReader.ReadLine();
It seems you only need the last line as the variable s is not used.
I have following code
using (StreamWriter outfile = new StreamWriter(#"f:\trial.cpp"))
{
outfile.Write(txtCode.InnerText);
}
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo(#"cl.exe", #" 'trial.cpp'");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.UserName = "asdasd";
SecureString secureString = new SecureString();
foreach (char c in "abcded")
{
secureString.AppendChar(c);
}
procStartInfo.Password = secureString;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
procStartInfo.WorkingDirectory = #"f:\";
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result = proc.StandardOutput.ReadToEnd();
How to pass file name as parameter? Above code doesn't run and I have tried all full path, different path options.
can anyone help?
The argument is set incorrectly. You have:
var procStartInfo = new ProcessStartInfo(#"cl.exe", #" 'trial.cpp'");
Where there are spaces and single quotes in the name. Try:
var procStartInfo = new ProcessStartInfo(#"cl.exe", #"trial.cpp");
EDIT:
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "CL.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = "trial.cpp";
try
{
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
}
}
catch
{
// error handling
}
The point here is that CL is a command line executable, not a windows GUI application.
http://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx
http://msdn.microsoft.com/en-us/library/kezkeayy.aspx
http://msdn.microsoft.com/en-us/library/9s7c9wdw.aspx
If the cl.exe is not in the system PATH (which by default it is not) then the start process will not find the executable and it will fail to run.
So I suspect you are seeing the fact that the cl.exe is not in the system PATH.