Межпроцессное взаимодействие между C# и Python

Я могу понять, что по этой теме было много вопросов, но ни один из них не мог решить мою проблему. Итак, здесь я представил свой код и хочу, чтобы мои ошибки были указаны здесь.

У меня есть программа, написанная на C#, которая должна вызывать исполняемый файл / файл Python. Первое требование заключается в том, что я должен передать один аргумент в файл Python через поток ввода. Это я мог сделать. Реальная проблема, с которой я сейчас сталкиваюсь, заключается в том, что мне нужно посмотреть, печатает ли мой файл python "Пожалуйста, введите аргумент_x", мне нужно прочитать этот вывод в моем коде C# и проверить, является ли он аргументом_x, а затем записать только значение аргумента в входной поток. Ниже приведены фрагменты кода для C# и Python.

Код C# выглядит следующим образом:

using System;
using System.IO;
using System.Diagnostics;
using System.ComponentModel;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            //Create a new process object
            Process myProcess = new Process();

            //Provide the start information for the process
            myProcess.StartInfo.FileName = "python.exe";
            myProcess.StartInfo.Arguments = "mytestpython.py";
            myProcess.StartInfo.UseShellExecute = false;
            myProcess.StartInfo.RedirectStandardInput = true;
            myProcess.StartInfo.RedirectStandardOutput = true;

            StreamReader myStreamReader;
            StreamWriter myStreamWriter;

            //Invoke the process from current process
            myProcess.Start();

            myStreamReader = myProcess.StandardOutput;

            //Read the standard output of the spawned process.
            string myString = myProcess.StandardOutput.ReadToEnd();
            Console.WriteLine(myString);

            if (myString.Contains("argument_x"))
            {
                myStreamWriter = myProcess.StandardInput;
                String argument = "argument_value";
                myStreamWriter.WriteLine(argument);
            }

           myProcess.WaitForExit();
           myStreamWriter.Close();
           myStreamReader.Close();
           myProcess.Close();
      }
   }
}

Программа на python в файле mytestpython.py выглядит следующим образом:

import sys
import getpass
prompt_string = "Please enter argument_x"
if sys.stdin.isatty():
    reqd_arg = getpass.getpass(prompt=prompt_string)
else:
    print(prompt_string)
    reqd_arg = sys.stdin.readline().rstrip()

Пожалуйста, помогите мне, так как я чувствую, что правильно написал 90% кода с небольшой ошибкой где-то посередине. Заранее спасибо за помощь.

3 ответа

Когда вы делаете myProcess.StandardOutput.ReadToEnd();, он пытается прочитать до конца стандартный вывод вашей программы на Python, то есть он будет ждать, пока программа Python завершит выполнение, и закроет свой поток стандартного вывода, чего он никогда не делает, потому что он ожидает ввода от вашей программы на C#. Это приводит к тупику.

ReadToEnd() полезно, когда родительский процесс ожидает завершения дочернего процесса. В случае интерактивного взаимодействия процессов, вы действительно должны рассмотреть возможность использования асинхронной связи с использованием BeginOutputReadLine проверьте документацию MSDN здесь для помощи

Я изменил код C#, чтобы принимать параметры CLI и передавать пароль в командной строке следующим образом:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Diagnostics;
    using System.ComponentModel;

    namespace Stub
    {
      class Program
        {
          static void Main(string[] args)
            {
            // Declare variables and initialize
            string passWord = string.Empty;
            string processArgs = getArguments(args); //Call getArguments method

            Console.Write("Please enter the system password : ");
            passWord = readPassword(); //call readPassword method

            Process p = new Process();

            p.StartInfo.FileName = "myexe.exe";
            p.StartInfo.Arguments = processArgs;
            p.StartInfo.WorkingDirectory = "my_working_directory";

            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = true;

            p.Start();
            StreamWriter sw = p.StandardInput;
            StreamReader sr = p.StandardOutput;

            writePassword(sr, sw, "password", passWord);

            sw.Close();
            sr.Close();
            p.WaitForExit();
            p.Close();
    }

    static string getArguments(string[] args)
    {
        StringBuilder procArgs = new StringBuilder();
        foreach (string arg in args)
        {
            procArgs.Append(arg);
            procArgs.Append(" ");
        }
        return procArgs.ToString();
    }



    static void writePassword(StreamReader sr, StreamWriter sw, string keyWord, string passWord)
    {
        string mystring;            
        do
        {
            mystring = sr.ReadLine();
        } while (!mystring.Contains(keyWord));
        if (mystring.Contains(keyWord))
            sw.WriteLine(passWord);
        else
            sw.WriteLine("\r\n");
    }

    static string readPassword()
    {
        string pass = string.Empty;
        ConsoleKeyInfo key;

        do
        {
            key = Console.ReadKey(true);
            if (key.Key != ConsoleKey.Backspace)
            {
                pass +=key.KeyChar;
                Console.Write("*");
            }
            else
            {
                if (pass.Length > 0)
                {
                    pass = pass.Substring(0, (pass.Length - 1));
                    Console.Write("\b \b");
                }
            }
        } while (key.Key != ConsoleKey.Enter);

        return pass;
    }
}

}

А потом просто небольшая модификация в Python:

    import sys
    import getpass
    prompt_string = "Please enter password"
    if sys.stdin.isatty():
        reqd_arg = getpass.getpass(prompt=prompt_string)
    else:
        print(prompt_string)
        sys.stdout.flush()
        reqd_arg = sys.stdin.readline().rstrip()

И вуаля.. это сработало!!!

Другие вопросы по тегам