在C#程序中使用bash(cygwin)
我需要在C#程序中使用bash shell。 我想模仿用户在交互模式下输入并运行cygwin命令。
我创建了一个运行bash并重定向stdin,stout和std错误的进程,但是我可以; tty得到tty来连接工作是一个启动bash进程并重定向输入/输出的示例代码。
问题是我没有tty设备。 如果我尝试运行tty命令或stty命令我收到错误响应
tty - not a tty
stty - Inappropriate ioctl for device
我认为这是由psi.UseShellExecute = false;
造成的psi.UseShellExecute = false;
我需要运行cygwin并禁用回声与stty -echo,但要做到这一点,我需要一个tty设备。 我怎么可以用tty设备创建一个cygwin bash shell并重定向stdin,out和error?
1)缺少什么?
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
namespace shartCygwin
{
class Program
{
private static Queue<string> ResponseQueue = null;
private static ManualResetEvent ResponseEvent = null;
static void Main(string[] args)
{
ResponseQueue = new Queue<string>();
ResponseEvent = new ManualResetEvent(false);
Process bashProcess = new Process();
bashProcess.StartInfo.FileName = "C:cygwinbinbash.exe";
bashProcess.StartInfo.Arguments = "--login -i ";
bashProcess.StartInfo.WorkingDirectory = "C:cygwinbin";
bashProcess.StartInfo.EnvironmentVariables["CYGWIN"] = "tty";
bashProcess.StartInfo.RedirectStandardError = true;
bashProcess.StartInfo.RedirectStandardInput = true;
bashProcess.StartInfo.RedirectStandardOutput = true;
bashProcess.StartInfo.CreateNoWindow = true;
bashProcess.StartInfo.UseShellExecute = false;
bashProcess.StartInfo.ErrorDialog = false;
bashProcess.Start();
DataReceivedEventHandler errorEventHandler = new DataReceivedEventHandler(ErrorDataReceived);
DataReceivedEventHandler outEventHandler = new DataReceivedEventHandler(OutDataReceived);
bashProcess.OutputDataReceived += outEventHandler;
bashProcess.ErrorDataReceived += errorEventHandler;
bashProcess.BeginErrorReadLine();
bashProcess.BeginOutputReadLine();
while(true)
{
Thread.Sleep(1000);
}
}
static void ErrorDataReceived(object sender, DataReceivedEventArgs dataReceivedEventArgs)
{
try
{
lock (ResponseQueue)
{
Console.WriteLine(dataReceivedEventArgs.Data);
ResponseQueue.Enqueue(dataReceivedEventArgs.Data);
ResponseEvent.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.Data);
}
}
static void OutDataReceived(object sender, DataReceivedEventArgs dataReceivedEventArgs)
{
try
{
lock (ResponseQueue)
{
Console.WriteLine(dataReceivedEventArgs.Data);
ResponseQueue.Enqueue(dataReceivedEventArgs.Data);
ResponseEvent.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.Data);
}
}
}
}
这可能会或可能不会帮助您或发生在此问题上的任何其他人。 这是Cygwin邮件列表中同一确切问题的答案。
> i created a process that runs bash and redirect stdin,stout and std error > but I can’t get tty to work attached is a sample code that starts bash > process and redirect the input/output. > the problem is that i don't have tty device. if i try to run tty command or > stty command i receive error response > tty - not a tty > stty - Inappropriate ioctl for device > i need to run cygwin and disable echo with stty -echo but to do this i need > a tty device. how can i create a cygwin bash shell with tty device and > redirect the stdin, out and error ? Why exactly do you think you need to run stty and set the tty operating parameters, when the bash process is quite plainly *not* connected to a tty, it is connected to your C# application? It's your application that is in charge of I/O - if it doesn't want echo, all it has to do is discard the stuff it reads from the process' stdout instead of displaying it, in your OutDataReceived/ErrorDataReceived handlers. > bashProcess.StartInfo.EnvironmentVariables["CYGWIN"] = "tty"; Don't do this. Win32 native processes don't understand Cygwin's tty emulation, which is based on pipes. cheers, DaveK
资料来源:http://www.cygwin.com/ml/cygwin/2009-09/msg00637.html
一个侧面说明,不是一个真正的答案,请看:http://www.codeproject.com/KB/IP/sharpssh.aspx
要回答这个问题:
您没有正确处理事件...您需要在收到的错误/输出事件处理程序中查找e.Data == null。 一旦两个事件处理程序收到此事件并且该过程已终止,您就完成了。 因此你等待三个句柄,一个告诉你Process.Exited事件被触发,一个告诉你错误输出收到null,一个告诉你输出收到null。 一定要设置:
process.EnableRaisingEvents = true;
以下是将输出重定向到当前控制台的完整答案:
static int RunProgram(string exe, params string[] args)
{
ManualResetEvent mreProcessExit = new ManualResetEvent(false);
ManualResetEvent mreOutputDone = new ManualResetEvent(false);
ManualResetEvent mreErrorDone = new ManualResetEvent(false);
ProcessStartInfo psi = new ProcessStartInfo(exe, String.Join(" ", args));
psi.WorkingDirectory = Environment.CurrentDirectory;
psi.RedirectStandardError = true;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
psi.UseShellExecute = false;
psi.ErrorDialog = true;
Process process = new Process();
process.StartInfo = psi;
process.Exited += delegate(object o, EventArgs e)
{
Console.WriteLine("Exited.");
mreProcessExit.Set();
};
process.OutputDataReceived += delegate(object o, DataReceivedEventArgs e)
{
if( e.Data != null )
Console.WriteLine("Output: {0}", e.Data);
else
mreOutputDone.Set();
};
process.ErrorDataReceived += delegate(object o, DataReceivedEventArgs e)
{
if (e.Data != null)
Console.Error.WriteLine("Error: {0}", e.Data);
else
mreErrorDone.Set();
};
process.EnableRaisingEvents = true;
Console.WriteLine("Start: {0}", process.StartInfo.FileName);
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
if (process.HasExited)
mreProcessExit.Set();
while(!WaitHandle.WaitAll(new WaitHandle[] { mreErrorDone, mreOutputDone, mreProcessExit }, 100))
continue;
return process.ExitCode;
}
只需执行如下操作:
C:cygwinbinbash -li /cygdrive/c/<path-to-shell-script-location>/chmod-cmd.sh
然后锁存到输入和输出。
或使用薄荷。
链接地址: http://www.djcxy.com/p/25699.html