2012-06-07 55 views
2

我可以理解,关于这个主题有很多问题,但他们都不能真正解决我的问题。所以我在这里提出了我的代码,我希望在这里指出我的错误。C#和Python之间的进程间通信

我有一个用C#编写的程序,它将调用一个python可执行文件/文件。第一个要求是我通过输入流传递一个参数给python文件。这我可以做。我现在面临的真正问题是,我必须查看我的python文件是否正在打印“请输入argument_x”,我必须在我的C#代码中读取此输出,并检查它是否为argument_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(); 
     } 
    } 
} 

mytestpython.py文件Python程序是这样的:

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%的代码,并在两者之间发生了一些小错误。在此先感谢您的帮助。

+1

确保您在每次输出后刷新或无法正常工作。 – Dani

+0

@Dani你能告诉我使用哪个函数吗? Autoflush什么的?究竟在哪里? –

+0

'myStreamWriter.WriteLine'把'myStreamWriter.Flush(');' – Dani

回答

4

当您执行myProcess.StandardOutput.ReadToEnd();时,它会尝试读取Python程序的标准输出的结尾,这意味着它将等待Python程序完成执行并关闭其stdout流,它永远不会执行,因为它正在等待输入来自您的C#程序。这会导致死锁。

+0

你是绝对正确的。但我真的需要等待输入流被python进程接受,只有当输出流令牌“argument_x”匹配它时。请提供任何解决方案,的代码,如果可能的话。 –

+0

@PRC_noob您需要逐字阅读并尝试匹配您阅读的内容和期望内容。 – univerio

+1

+1 ReadToEnd – GETah

3

ReadToEnd()在父进程等待子进程完成时非常有用。在互动过程中通信的情况下,你真的应该考虑使用使用BeginOutputReadLine检查MSDN文档here异步通信的帮助

+0

找到了解决方案,感谢您的帮助:) –

+2

@PRC_noob请不要忘记给所有人一些奖励(+1)谁已经帮助你解决了你的问题:)并且接受你所看到的与你发现的解决方案非常接近的答案; – GETah

2

我修改了C#代码接受CLI PARAMS,并就迅速传递密码的方法如下:

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

而且瞧,这工作!

+1

+1发布答案!做得好 – GETah