Open Program from C# - also specifying the working directory - c#

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

Related

TeraTerm macro immediately closes when run as a process from c#

I'm currently working on a Winforms program from Visual Studio that acts as a control panel for a whole bunch of TeraTerm macros. I did a dumb and didn't add my first working version to version control, and now it's stopped working and I have no idea why/how to get back to what I had.
The function is question is
using System;
using System.IO.Ports;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Diagnostics;
...
namespace Test
{
public partial class MainWindow : Form
{
...
private void ImagesButton_Click(object sender, EventArgs e)
{
RunMacro("F:\\Users\\Isaac\\Documents\\LED Sign Commands\\Macros\\StartDisplayImages.ttl");
}
....
private void RunMacro(string userArgument)
{
panel1.Enabled = false;
StatusLabel.Visible = true;
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo()
{
WindowStyle = ProcessWindowStyle.Hidden,
#if DEBUG
FileName = "F:\\Users\\Isaac\\Documents\\LED Sign Commands\\teraterm\\ttpmacro.exe",
#else
FileName = "..\\teraterm\\ttpmacro.exe",
#endif
Arguments = userArgument
};
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
panel1.Enabled = true;
StatusLabel.Visible = false;
}
...
}
}
When run, I see that ttpmacro.exe does start, and if I omit the Arguments assignment then it will prompt me to select a macro; if I select StartDisplayImages.ttl, it will run as expected. If I include it as an argument as above, however, then ttpmacro still opens but immediately closes. No error comes up (and RedirectStandardOutput/Error produce nothing), it's as if ttpmacro accepts the file but won't do anything with it. I've confirmed both filepaths are valid and correct.
While I didn't add version control, I did extract the main file using ILSpy, and my original functions in the working version were:
private void ImagesButton_Click(object sender, EventArgs e)
{
RunMacro("/V ..\\Macros\\StartDisplayImages.ttl");
}
private void RunMacro(string userArgument)
{
panel1.Enabled = false;
StatusLabel.Visible = true;
Process process = new Process();
ProcessStartInfo startInfo = (process.StartInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Hidden,
FileName = "..\\teraterm\\ttpmacro.exe",
Arguments = userArgument
});
process.Start();
process.WaitForExit();
panel1.Enabled = true;
StatusLabel.Visible = false;
}
Being from the published release, the filepaths are relative to the folder of the application. Other than that, the only difference seems to be minor syntax in how process.StartInfo is assigned, but I tried reverting that with no luck. Target framework is .NET Core 3.1. The /V flag isn't the issue; removing it simply makes the ttpmacro window visible for the fraction of a second it runs before closing. If I use a commandline execution of the same file (eg start "F:/Users/.../ttpmacro.exe" "F:/.../StartDisplayImages.ttl"), it also runs as expected.
It turned out the problem was the spaces in the full macro filepath, and surrounding it with escaped double quotes resolved the issue. TeraTerm just wasn't telling me that it wasn't finding the file. Should have been obvious, but I was sure it had been working previously when I was debugging, without requiring the quotes.

Embed Python in C# Windows Application [duplicate]

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

%~dp0 and running batch file from C# [duplicate]

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

Input from forms can't execute .bat file

Hi everyone I've been creating this program for a day now. But it seems that I can't get it to work. What I want is, I have a windows form, who will get the IP address input and will execute a .bat file.
#echo off
wmic /node:x computersystem get username
where x is the string variable for my IP.
the command will print out the current logged in username.
Here's my c# code:
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace wmic_forms
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public string x;
private void button1_Click(object sender, EventArgs e)
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "C:\\ken.bat";
Process p = Process.Start(psi);
string strOutput = p.StandardOutput.ReadToEnd();
//p.WaitForExit();
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.Arguments = textBox1.Text;
MessageBox.Show(strOutput);
//Console.WriteLine(strOutput);
//Console.ReadLine();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
//my input text box for IP
x = textBox1.Text;
}
}
}
The code runs with no error. But it would only print out the entire strings from .bat file. Please give me feedback on how can I pass variable x to .bat file and execute its command.
You don't need a batch file to do that, simply run wmic with those parameters. And you especially don't need to follow malware practices of storing files in system folders, like the C: drive.
As to the specific problem in your code, you're setting the process object's properties after you launch it instead of before. Of course they don't matter anymore.
And while we're on the topic of refactoring, I'll remind you that it's not 1985 anymore to launch chains of scripts because the OS doesn't expose its inner workings. You can easily access the WMI API directly from C# using managed classes: https://msdn.microsoft.com/en-us/library/system.management.managementscope(v=vs.110).aspx

Can we create our own process in C#?

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.

Categories

Resources