as described in the title, I wanna open up the ubuntu-shell on my windows pc, passing a
"cd /mnt/c/users/xyz/desktop" to it then passing a
"python3 some_script.py arg1, arg2" to it
all this works wonderful if done manually via mouseclicks but from code (see below:)
it doesnt write anything to the console which opens.
string ExecuteCommand(string command)
{
// Execute wsl command:
var StartInfo = new ProcessStartInfo
{
FileName = #"bash.exe",
WorkingDirectory = #"C:\Windows\System32",
//Arguments = "/c " + "root#DESKTOP-OUTEVME:~#",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
RedirectStandardError = true,
CreateNoWindow = false,
WindowStyle = ProcessWindowStyle.Normal,
};
using (var process = Process.Start(StartInfo))
{
process.StandardInput.WriteLine();
process.EnableRaisingEvents = true;
process.OutputDataReceived += (s, e) => MessageBox.Show(e.Data);
process.BeginOutputReadLine();
process.StandardInput.WriteLine(command);
process.StandardInput.WriteLine("exit");
process.WaitForExit();
//result = process.StandardOutput.ReadToEndAsync().Result;
}
return result;
}
return ExecuteCommand(#"wsl cd /mnt/c/users/shho3/desktop");
Anyone maybe an idea what I could do wrong?
Much thanks!
You could pass everything in the command line instead of piping into the process. I think it would save you a lot of trouble. Try bash.exe -c "cd /mnt/c/Users/shho3/Desktop; python some_script.py arg1 arg2":
Process.Start("bash.exe", "-c \"cd /mnt/c/Users/shho3/Desktop; python some_script.py arg1 arg2\"").WaitForExit()
Alternatively you can also just set the working directory to C:\Users\shho3\Desktop (instead of C:\Windows\System32) and call bash.exe -c "python some_script.py arg1 arg2", then you don't even have to convert the path:
Process.Start(new ProcessStartInfo("bash.exe", "-c \"python some_script.py arg1 arg2\"") {
WorkingDirectory = "C:\\Users\\ssho3\\Desktop"
}).WaitForExit()
Related
I'm trying to open run a few arguments using cmd.exe from ProcessStartInfo in C#
but my folder navigation needs to include double quotes eg. "C:\this is\my\folder site"
as you see the reason for using double quotes is because the folders have space on their name.
this is my code
var ddd = "\"" + projectPath + "\"";
var strCmdTxt = "/c cd " + ddd + " && code .";
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo
{
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
FileName = "cmd.exe",
Arguments = strCmdTxt, UseShellExecute = true, CreateNoWindow= true
};
process.StartInfo = startInfo;
process.Start();
BUT, what it runs is something like this
cd\ "C:\this is\my\folder site\"
which, just returns me to C drive
The command should be cd "C:\this is\my\folder site"
Looks like what you're trying to achieve is start VS Code in the specified folder. Consider using the working directory of the process you're starting, instead of trying to navigate to that directory and starting VS Code in there. Here is a method to help with that:
private static void StartVSCodeInFolder(string projectPath)
{
using (System.Diagnostics.Process process = new System.Diagnostics.Process())
{
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo
{
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
FileName = "C:/Program Files/Microsoft VS Code/Code.exe",
Arguments = ".",
UseShellExecute = false,
CreateNoWindow = true,
WorkingDirectory = projectPath
};
process.StartInfo = startInfo;
process.Start();
}
}
Hope this helps.
Could you not change the working directory using the Environment class and simply using "code.exe".
It seems like it would be a cleaner approach.
Environment.CurrentDirectory = #"C:\Program Files\Microsoft VS Code";
I am trying to send commands to an open cmd.exe process using StandardInput.WriteLine(str), however none of the commands seem to be sent. First I open a process, with a global variable p (Process p).
p = new Process()
{
StartInfo = {
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
FileName = #"cmd.exe",
Arguments = "/C" //blank arguments
}
};
p.Start();
p.WaitForExit();
After, I try to send a command using a simple method, that logs the result in a text box.
private void runcmd(string command)
{
p.StandardInput.WriteLine(command);
var output = p.StandardOutput.ReadToEnd();
TextBox1.Text = output;
}
Right now I am testing it with DIR, but var output shows up as null, which results in no output. Is there a better way to send a command to the open cmd.exe process?
I could never get it to work with synchronous reads of stdout without closing stdin, but it does work with async reading for stdout/stderr. No need to pass in /c, you only do that when passing in a command through the arguments; you are not doing this though, you are sending the command directly to the input.
var p = new Process()
{
StartInfo = {
CreateNoWindow = false,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
FileName = #"cmd.exe"}
};
p.OutputDataReceived += (sender, args1) => Console.WriteLine(args1.Data);
p.ErrorDataReceived += (sender, args1) => Console.WriteLine(args1.Data);
p.Start();
p.BeginOutputReadLine();
p.StandardInput.WriteLine("dir");
p.StandardInput.WriteLine("cd e:");
p.WaitForExit();
Console.WriteLine("Done");
I am trying to make a directory using this code to see if the code is executing but for some reason it executes with no error but the directory is never made. Is there and error in my code somewhere?
var startInfo = new
var startinfo = new ProcessStartInfo();
startinfo.WorkingDirectory = "/home";
proc.StartInfo.FileName = "/bin/bash";
proc.StartInfo.Arguments = "-c cd Desktop && mkdir hey";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start ();
Console.WriteLine ("Shell has been executed!");
Console.ReadLine();
This works best for me because now I do not have to worry about escaping quotes etc...
using System;
using System.Diagnostics;
class HelloWorld
{
static void Main()
{
// lets say we want to run this command:
// t=$(echo 'this is a test'); echo "$t" | grep -o 'is a'
var output = ExecuteBashCommand("t=$(echo 'this is a test'); echo \"$t\" | grep -o 'is a'");
// output the result
Console.WriteLine(output);
}
static string ExecuteBashCommand(string command)
{
// according to: https://stackoverflow.com/a/15262019/637142
// thans to this we will pass everything as one command
command = command.Replace("\"","\"\"");
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "/bin/bash",
Arguments = "-c \""+ command + "\"",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
proc.WaitForExit();
return proc.StandardOutput.ReadToEnd();
}
}
This works for me:
Process.Start("/bin/bash", "-c \"echo 'Hello World!'\"");
My guess is that your working directory is not where you expect it to be.
See here for more information on the working directory of Process.Start()
also your command seems wrong, use && to execute multiple commands:
proc.StartInfo.Arguments = "-c cd Desktop && mkdir hey";
Thirdly you are setting your working directory wrongly:
proc.StartInfo.WorkingDirectory = "/home";
I have one file which contains a Unix shell script. So now I wanted to
run the same in .NET. But I am unable to execute the same.
So my point is, is it possible to run the Unix program in .NET? Is there any API like NSTask in Objective-C for running Unix shell scripts so any similar API in .NET?
It has been answered before. Just check this out.
By the way, you can use:
Process proc = new Process {
StartInfo = new ProcessStartInfo {
FileName = "program.exe",
Arguments = "command line arguments to your executable",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
After that start the process and read from it:
proc.Start();
while (!proc.StandardOutput.EndOfStream) {
string line = proc.StandardOutput.ReadLine();
// Do something with line
}
ProcessStartInfo frCreationInf = new ProcessStartInfo();
frCreationInf.FileName = #"C:\Program Files\Git\git-bash.exe";
frCreationInf.Arguments = "Test.sh";
frCreationInf.UseShellExecute = false;
var process = new Process();
process.StartInfo = frCreationInf;
process.Start();
process.WaitForExit();
I wanna redirect cmd.exe output somewhere, below code works when the command is a line:
Process p = new Process()
{
StartInfo = new ProcessStartInfo("cmd")
{
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
CreateNoWindow = true,
Arguments = String.Format("/c \"{0}\"", command),
}
};
p.OutputDataReceived += (s, e) => Messagebox.Show(e.Data);
p.Start();
p.BeginOutputReadLine();
p.WaitForExit();
But how about a series commands like WriteLine():
p.StandardInput.WriteLine("cd...");
p.StandardInput.WriteLine("dir");
how to get output in this situation?
To achieve such behavior you should use /k switch to run cmd.exe in interactive mode.
The problem is to separate inputs from different commands.
To do this you could change the standard prompt using prompt command:
prompt --Prompt_C2BCE8F8E2C24403A71CA4B7F7521F5B_F659E9F3F8574A72BE92206596C423D5
So now it is pretty easy to determine the end of command output.
Here is the complete code:
public static IEnumerable<string> RunCommands(params string[] commands) {
var process = new Process {
StartInfo = new ProcessStartInfo("cmd") {
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
CreateNoWindow = true,
Arguments = "/k",
}
};
process.Start();
const string prompt = "--Prompt_C2BCE8F8E2C24403A71CA4B7F7521F5B_F659E9F3F8574A72BE92206596C423D5 ";
// replacing standard prompt in order to determine end of command output
process.StandardInput.WriteLine("prompt " + prompt);
process.StandardInput.Flush();
process.StandardOutput.ReadLine();
process.StandardOutput.ReadLine();
var result = new List<string>();
try {
var commandResult = new StringBuilder();
foreach (var command in commands) {
process.StandardInput.WriteLine(command);
process.StandardInput.WriteLine();
process.StandardInput.Flush();
process.StandardOutput.ReadLine();
while (true) {
var line = process.StandardOutput.ReadLine();
if (line == prompt) // end of command output
break;
commandResult.AppendLine(line);
}
result.Add(commandResult.ToString());
commandResult.Clear();
}
} finally {
process.Kill();
}
return result;
}
It works well but it looks like one big hack.
I'd recommend you to use process per command instead.