I need to run a Python script from my C# program and see the result. But my below code isn't working, the working directory changes but it doesn't seem like Arguments part is run. The commented line (writeline) is me trying to send commands after opening cmd because sending them as arguments didn't work. That is giving an error (Message "StandardIn has not been redirected.) and Googling gave me that UseShellExecute needs to be false but that didn't work.
Attached image shows how command prompt opens.
private void run_cmd(string pathPythonExe, string pathPyFolder, string SN)
{
Process p = new Process();
p.StartInfo.FileName = "C:\\Windows\\system32\\cmd.exe";
p.StartInfo.WorkingDirectory = pathPyFolder;
p.StartInfo.Arguments = pathPythonExe + " Z19003.py --sn " + SN;
p.StartInfo.UseShellExecute = false;
p.Start();
//p.StandardInput.WriteLine(pathPythonExe + " Z19003.py --sn " + SN);
I've tried different ways to open cmd and run that I found online but nothing seems to work. Running the Python script works if I just copy-paste the command to command prompt. But I want to automate that part.
Firstly, let's break the semantics of a process. A process is a program which is currently running and its operation status is kept under observation by the OS by using multiple monitoring techniques. Now the question is how a process can communicate with other programs, and the OS itself, and vice-versa? The answer lies in one fundamental characteristic of every OS kernel, and that is the STDIN, STOUT, and STDERR Input / Output ( I/O ) streams. The STDIN stream is responsible for processing input related data, the STDOUT is responsible for processing output related data, and the STDERR stream is responsible for processing error messages related data. These streams are used by processes and the OS itself to process input, process output, and process errors, and these streams are necessary for the processes to process all the I/O information.
Process p = new Process();
p.StartInfo.FileName = "C:\\Windows\\system32\\cmd.exe";
p.StartInfo.WorkingDirectory = pathPyFolder;
p.StartInfo.Arguments = pathPythonExe + " Z19003.py --sn " + SN;
p.StartInfo.UseShellExecute = false;
p.Start();
In the code shown above, the output given by the Python script cannot be seen because the input given by the script is sent through the OS itself and not to the C# application, because the STDOUT stream was not redirected to go through the C# application.
p.StartInfo.UseShellExecute = false;
The line shown above means that the Python script will be started by the C# application, not the OS shell, which is necessary when redirecting the STDOUT stream. To redirect the STDOUT stream, the propriety of the Process class named RedirectStandardOutput
must be set to true, p.StartInfo.RedirectStandardOutput = true;
. To run the Python script, you need to run the Python interpreter and pass the name of the script file as an argument to be run. To run the Python interpreter you either call the python
command or run the Python interpreter executable by calling it through its path (e.g.C:\Users\John\...\Python 3.10\python.exe
). To start the Python interpreter, you must set either the path to the Python interpreter or the Python command as the value of the FileName
propriety of the Process
class, and this is shown below.
// WHEN USING PATHS PUT THE PATH BETWEEN (") IN ORDER
// TO FORMAT WHITE SPACES AND TREAT THEM AS STRINGS
p.StartInfo.FileName = "python"; //Python command
// OR
// Path to Python interpreter
p.StartInfo.FileName = "\"C:\\Users\\John\\...\\Python 3.10\\python.exe\"";
To run the desired script, it must be passed as an argument to the interpreter by setting the Arguments
propriety of the Process class as the path to the Python script p.StartInfo.Arguments = "C:\\Users\\John\\script.py";
. The resulting code that starts the Python interpreter, runs the script, and sets the STDOUT stream to be redirected through the C# application is shown below.
// WHEN USING PATHS PUT THE PATH BETWEEN (") IN ORDER
// TO FORMAT WHITE SPACES AND TREAT THEM AS STRINGS
using System.Diagnostics;
Process p = new Process();
p.StartInfo.FileName = "python";
p.StartInfo.Arguments = "\"C:\\Users\\John\\script.py\""
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
To read the STDOUT stream sent by the application, the ReadLine()
method of the Process class must be called.
// WHEN USING PATHS PUT THE PATH BETWEEN (") IN ORDER
// TO FORMAT WHITE SPACES AND TREAT THEM AS STRINGS
using System.Diagnostics;
Process p = new Process();
p.StartInfo.FileName = "python";
p.StartInfo.Arguments = "\"C:\\Users\\John\\script.py\""
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
Console.WriteLine(p.StandardOutput.ReadLine());
print("!!! Message from Python script !!!")