Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#程序中使用bash(cygwin)_C#_Bash_Process_Cygwin - Fatal编程技术网

在C#程序中使用bash(cygwin)

在C#程序中使用bash(cygwin),c#,bash,process,cygwin,C#,Bash,Process,Cygwin,我需要使用bashshell“内部”C#程序。我想模拟用户在交互模式下键入并运行cygwin命令 我创建了一个运行bash和重定向stdin、stout和std error的进程,但我可以;t get tty to work attached是启动bash进程并重定向输入/输出的示例代码 问题是我没有tty设备。如果我尝试运行tty命令或stty命令,我将收到错误响应 tty - not a tty stty - Inappropriate ioctl for device 我认为这是由于p

我需要使用bashshell“内部”C#程序。我想模拟用户在交互模式下键入并运行cygwin命令

我创建了一个运行bash和重定向stdin、stout和std error的进程,但我可以;t get tty to work attached是启动bash进程并重定向输入/输出的示例代码


问题是我没有tty设备。如果我尝试运行tty命令或stty命令,我将收到错误响应

tty - not a tty 
stty - Inappropriate ioctl for device
我认为这是由于
psi.UseShellExecute=false

我需要运行cygwin并使用stty-echo禁用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:\\cygwin\\bin\\bash.exe"; 
            bashProcess.StartInfo.Arguments = "--login -i ";  
            bashProcess.StartInfo.WorkingDirectory = "C:\\cygwin\\bin";

            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);
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
使用系统文本;
使用系统线程;
名称空间shartCygwin
{
班级计划
{
私有静态队列ResponseQueue=null;
专用静态手动重置事件响应事件=null;
静态void Main(字符串[]参数)
{
ResponseQueue=新队列();
ResponseEvent=新手动重置事件(假);
Process bashProcess=新流程();
bashProcess.StartInfo.FileName=“C:\\cygwin\\bin\\bash.exe”;
bashProcess.StartInfo.Arguments=“--login-i”;
bashProcess.StartInfo.WorkingDirectory=“C:\\cygwin\\bin”;
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();
DataReceiveDevenHandler errorEventHandler=新DataReceiveDevenHandler(ErrorDataReceived);
DataReceivedEventHandler outEventHandler=新的DataReceivedEventHandler(OutDataReceived);
bashProcess.OutputDataReceived+=outEventHandler;
bashProcess.ErrorDataReceived+=errorEventHandler;
bashProcess.BeginErrorReadLine();
bashProcess.BeginOutputReadLine();
while(true)
{
睡眠(1000);
}
}
静态无效错误DataReceived(对象发送方、DataReceivedEventArgs DataReceivedEventArgs)
{
尝试
{
锁(应答器)
{
Console.WriteLine(dataReceivedEventArgs.Data);
响应队列(dataReceivedEventArgs.Data);
ResponseEvent.Set();
}
}
捕获(例外e)
{
控制台写入线(如数据);
}
}
静态void OutDataReceived(对象发送方、DataReceivedEventArgs DataReceivedEventArgs)
{
尝试
{
锁(应答器)
{
Console.WriteLine(dataReceivedEventArgs.Data);
响应队列(dataReceivedEventArgs.Data);
ResponseEvent.Set();
}
}
捕获(例外e)
{
控制台写入线(如数据);
}
}
}
}

一个旁注,而不是真正的答案,看看:

要回答这个问题:

您没有正确处理事件。。。您需要在接收到的错误/输出的事件处理程序中查找e.Data==null。一旦两个事件处理程序都接收到此事件并且进程终止,您就完成了。因此,您需要等待三个句柄,一个告诉您流程。已触发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;
    }

这可能会也可能不会帮助你或任何遇到这个问题的人。这是对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 >我创建了一个运行bash和重定向stdin、stout和std error的进程 >但我无法让tty工作。附加的是启动bash的示例代码 >处理并重定向输入/输出。
>问题是我没有tty设备。如果我尝试运行tty命令或 >stty命令我收到错误响应 >tty-不是tty >stty-设备的ioctl不正确 >我需要运行cygwin并使用stty-echo禁用echo,但要做到这一点,我需要 >一种轻巧的装置。如何使用tty设备和 >重定向标准输入、输出和错误? 为什么您认为您需要运行stty并将tty设置为运行状态 参数,当bash进程非常明显地*未*连接到tty时, 它是否连接到您的C#应用程序? 是您的应用程序负责I/O—如果它不需要echo, 它所要做的就是丢弃从进程stdout读取的内容 而不是在OutDataReceived/ErrorDataReceived处理程序中显示它。 >bashProcess.StartInfo.EnvironmentVariables[“CYGWIN”]=“tty”; 不要这样做。Win32本机进程不理解Cygwin的tty 基于管道的仿真。 干杯 达维克
来源:

只需执行类似以下内容:

C:\cygwin\bin\bash -li /cygdrive/c/<path-to-shell-script-location>/chmod-cmd.sh 
C:\cygwin\bin\bash-li/cygdrive/C//chmod-cmd.sh
然后锁定输入和输出


或者使用。

问题是我没有tty设备。如果我尝试运行tty命令或stty命令,我会收到错误响应tty-不是tty stty-设备的ioctl不适当,我认为这是由psi.UseShellExecute=false引起的;我需要运行cygwin并使用stty-echo禁用echo,但要做到这一点,我需要一个tty设备。如何使用tty d创建cygwin bash shell