I need to create 3 processes in 1 program to simulate deadlock. How can I define my own process? I don't want to simply open an existing process.
For example for a thread:
Thread X = new Thread(){ //insert whatever code here// };
How can we do this for a process, like:
Process P = new Process(){//insert different threads here//};
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Process process = new Process();
process.StartInfo.FileName = "notepad";
//process.StartInfo.Arguments = "filename.txt"
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();
}
}
}
Processes come from executable files.
You can write Process.Start(#"C:\Something.exe").
You probably looking for Process.Start (either static or instance method) - which will create new process by launching executable of your choice.
If you looking for implementation of fork from Unix you can't really do that in .Net to my knowledge.
Code in one process cannot be executed in another process. You need some form of inter-process communication, or remote procedure call.
Related
This sort of question has been asked before in varying degrees, but I feel it has not been answered in a concise way and so I ask it again.
I want to run a script in Python. Let's say it's this:
if __name__ == '__main__':
with open(sys.argv[1], 'r') as f:
s = f.read()
print s
Which gets a file location, reads it, then prints its contents. Not so complicated.
Okay, so how do I run this in C#?
This is what I have now:
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = cmd;
start.Arguments = args;
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
When I pass the code.py location as cmd and the filename location as args it doesn't work. I was told I should pass python.exe as the cmd, and then code.py filename as the args.
I have been looking for a while now and can only find people suggesting to use IronPython or such. But there must be a way to call a Python script from C#.
Some clarification:
I need to run it from C#, I need to capture the output, and I can't use IronPython or anything else. Whatever hack you have will be fine.
P.S.: The actual Python code I'm running is much more complex than this, and it returns output which I need in C#, and the C# code will be constantly calling the Python code.
Pretend this is my code:
private void get_vals()
{
for (int i = 0; i < 100; i++)
{
run_cmd("code.py", i);
}
}
The reason it isn't working is because you have UseShellExecute = false.
If you don't use the shell, you will have to supply the complete path to the python executable as FileName, and build the Arguments string to supply both your script and the file you want to read.
Also note, that you can't RedirectStandardOutput unless UseShellExecute = false.
I'm not quite sure how the argument string should be formatted for python, but you will need something like this:
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "my/full/path/to/python.exe";
start.Arguments = string.Format("{0} {1}", cmd, args);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using(Process process = Process.Start(start))
{
using(StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
If you're willing to use IronPython, you can execute scripts directly in C#:
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
private static void doPython()
{
ScriptEngine engine = Python.CreateEngine();
engine.ExecuteFile(#"test.py");
}
Get IronPython here.
Execute Python script from C
Create a C# project and write the following code.
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
run_cmd();
}
private void run_cmd()
{
string fileName = #"C:\sample_script.py";
Process p = new Process();
p.StartInfo = new ProcessStartInfo(#"C:\Python27\python.exe", fileName)
{
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
Console.ReadLine();
}
}
}
Python sample_script
print "Python C# Test"
You will see the 'Python C# Test' in the console of C#.
I ran into the same problem and Master Morality's answer didn't do it for me. The following, which is based on the previous answer, worked:
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = cmd;//cmd is full path to python.exe
start.Arguments = args;//args is path to .py file and any cmd line args
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using(Process process = Process.Start(start))
{
using(StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
As an example, cmd would be #C:/Python26/python.exe and args would be C://Python26//test.py 100 if you wanted to execute test.py with cmd line argument 100. Note that the path the .py file does not have the # symbol.
Actually its pretty easy to make integration between Csharp (VS) and Python with IronPython. It's not that much complex... As Chris Dunaway already said in answer section I started to build this inegration for my own project. N its pretty simple.
Just follow these steps N you will get your results.
step 1 : Open VS and create new empty ConsoleApp project.
step 2 : Go to tools --> NuGet Package Manager --> Package Manager Console.
step 3 : After this open this link in your browser and copy the NuGet Command.
Link: https://www.nuget.org/packages/IronPython/2.7.9
step 4 : After opening the above link copy the PM>Install-Package IronPython -Version 2.7.9
command and paste it in NuGet Console in VS.
It will install the supportive packages.
step 5 : This is my code that I have used to run a .py file stored in my Python.exe
directory.
using IronPython.Hosting;//for DLHE
using Microsoft.Scripting.Hosting;//provides scripting abilities comparable to batch files
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
class Hi
{
private static void Main(string []args)
{
Process process = new Process(); //to make a process call
ScriptEngine engine = Python.CreateEngine(); //For Engine to initiate the script
engine.ExecuteFile(#"C:\Users\daulmalik\AppData\Local\Programs\Python\Python37\p1.py");//Path of my .py file that I would like to see running in console after running my .cs file from VS.//process.StandardInput.Flush();
process.StandardInput.Close();//to close
process.WaitForExit();//to hold the process i.e. cmd screen as output
}
}
step 6 : save and execute the code
Set WorkingDirectory or specify the full path of the python script in the Argument
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "C:\\Python27\\python.exe";
//start.WorkingDirectory = #"D:\script";
start.Arguments = string.Format("D:\\script\\test.py -a {0} -b {1} ", "some param", "some other param");
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
I am having problems with stdin/stout - when payload size exceeds several kilobytes it hangs. I need to call Python functions not only with some short arguments, but with a custom payload that could be big.
A while ago, I wrote a virtual actor library that allows to distribute task on different machines via Redis. To call Python code, I added functionality to listen for messages from Python, process them and return results back to .NET.
Here is a brief description of how it works.
It works on a single machine as well, but requires a Redis instance. Redis adds some reliability guarantees - payload is stored until a worked acknowledges completion. If a worked dies, the payload is returned to a job queue and then is reprocessed by another worker.
had same issure and this worked for me:
using IronPython.Hosting;
var engine = Python.CreateEngine();
engine.ExecuteFile("") //put the directory of the program in the quote marks
I have some code that launches an external program, although is it possible to specify the working directory, as the external program is a console program:
Code:
private void button5_Click_2(object sender, EventArgs e)
{
System.Diagnostics.Process.Start(#"update\update.exe");
}
Yes, it's possible, use ProcessStartInfo object to specify all the params you need and then just pass it to the Start method like that:
...
using System.Diagnostics;
...
var psi = new ProcessStartInfo(#"update\update.exe");
psi.WorkingDirectory = #"C:\workingDirectory";
Process.Start(psi);
You can specify the Working Directory using ProcessStartInfo.WorkingDirectory.
...
using System.Diagnostics;
...
var processStartInfo = new ProcessStartInfo(#"explorer.exe");
processStartInfo.WorkingDirectory = #"C:\";
var process = Process.Start(processStartInfo);
I'm trying to write a wrapper for an interactive console-based application. For this I use C# and the Process class. I'm trying to redirect stdin/out/err, but it doesn't work.
Example code:
ProcessStartInfo startInfo = new ProcessStartInfo("admin.exe");
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;
Process process = Process.Start(startInfo);
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
while (true)
{
process.StandardInput.Write("uptime" + Environment.NewLine);
process.StandardInput.Flush();
Thread.Sleep(1000);
}
Console.ReadKey();
Nothing happens. But if I start admin.exe and write uptime, output is printed.
All solutions in the internet use ReadToEnd, but I can't use this because i have a dynamic communication on which I have to read stdout/err and write to stdin.
Has anyone an idea?
Update
I played with the posted zip on the linked thread. And then i tried to create a small 'proof-of-concept'-code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Threading;
namespace ConsoleApplication3
{
class Program
{
private static void Read(StreamReader reader)
{
new Thread(() =>
{
while (true)
{
int current;
while ((current = reader.Read()) >= 0)
Console.Write((char)current);
}
}).Start();
}
static void Main(string[] args)
{
ProcessStartInfo startInfo = new ProcessStartInfo(#"cmd.exe");
startInfo.CreateNoWindow = true;
startInfo.ErrorDialog = false;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
Read(process.StandardOutput);
Read(process.StandardError);
while (true)
process.StandardInput.WriteLine(Console.ReadLine());
}
}
}
It works perfectly:-)
But with the admin.exe it doesn't work? The admin.exe doesn't use any tricky input-method and it doesn't need an inputed password.
I know the admin.exe is written in c and compiled with mingw on linux. So i created a small dummy-tool:
#include <stdio.h>
int main() {
int readed;
while ((readed = fgetc(stdin)) >= 0)
fputc((char)readed, stdout);
}
This tool does only echo the inputed text/line. I compiled it with i586-mingw32msvc-gcc and copied it to my windows machine. There i used the program on the top of this post to communicate with the dummy.exe. It doesn't work. No echo is shown. But why?
I compiled the dummy-code also with the Microsoft C++ Compiler, same effect.
Update2
(btw: Thanks to Tim Post)
I'm trying and trying. I tried to create a c-Tool, which does the same as my c# tool. I used _popen, but the effect was, that the output were shown at the end of the process. Hm, not good.
I found this alternative command shell for windows:
https://stackoverflow.com/questions/440269/whats-a-good-alternative-windows-console
http://sourceforge.net/projects/console/
It seems to work. It gets the stdout/err in realtime, can redirect the stdin and admin.exe works. And it is opensource. May be i'll find the solution inside the C++-Code.
I'm not well in C++, so it's hard, but i'll try it. May be i have to write a "clear" redirect-wrapper in C/C++ and use it in C#.
If someone has an idea please say it, because the other way can be very hard (for me^^):-)
Thanks.
best regards
Update 3
Hm, i think this happens because the child-process (admin.exe) uses a few threads...
But how to solve it?
The problem could be because of you are using Readline, where the data are output from admin.exe application are sequentially and not in new lines.., try to use Read instead, and build the desirable string from it..
Also you don't have to use Environment.NewLine to write string followed by new line, use WriteLine instead, so:
process.StandardInput.WriteLine("uptime");
I have some code that launches an external program, although is it possible to specify the working directory, as the external program is a console program:
Code:
private void button5_Click_2(object sender, EventArgs e)
{
System.Diagnostics.Process.Start(#"update\update.exe");
}
Yes, it's possible, use ProcessStartInfo object to specify all the params you need and then just pass it to the Start method like that:
...
using System.Diagnostics;
...
var psi = new ProcessStartInfo(#"update\update.exe");
psi.WorkingDirectory = #"C:\workingDirectory";
Process.Start(psi);
You can specify the Working Directory using ProcessStartInfo.WorkingDirectory.
...
using System.Diagnostics;
...
var processStartInfo = new ProcessStartInfo(#"explorer.exe");
processStartInfo.WorkingDirectory = #"C:\";
var process = Process.Start(processStartInfo);
Just like the subject states. I want to be able to run iisreset, batch files, etc. from the a console application. Can I/How do I do it?
That's quite possible, for example:
System.Diagnostics.Process.Start(#"C:\listfiles.bat");
Check this example from C# Station
using System;
using System.Diagnostics;
namespace csharp_station.howto
{
/// <summary>
/// Demonstrates how to start another program from C#
/// </summary>
class ProcessStart
{
static void Main(string[] args)
{
Process notePad = new Process();
notePad.StartInfo.FileName = "notepad.exe";
notePad.StartInfo.Arguments = "ProcessStart.cs";
notePad.Start();
}
}
}
You can also do this:
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo();
info.UseShellExecute = true;
info.FileName = "iisreset";
System.Diagnostics.Process.Start(info);
Console.ReadLine();