如何在Go和C#控制台应用程序之间建立长期管道连接

yftpprvb  于 2023-11-14  发布在  Go
关注(0)|答案(2)|浏览(151)

我有一个非常简单的C#控制台应用程序。它将是一个添加double变量的过程,这些变量是从go部分传递过来的。

  1. double sum = 0;
  2. bool flag = true;
  3. while(flag) { // exit on convert error
  4. var str = Console.ReadLine(); // ask string
  5. double addend;
  6. flag = double.TryParse(str, out addend); // convert to double
  7. sum += flag ? addend : 0; //add on success
  8. Console.WriteLine(sum);
  9. }
  10. return 0;

字符串
我的go部分也很简单。它用以前的控制台应用程序创建进程,发送字符串并读回结果。

  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "log"
  6. "os/exec"
  7. )
  8. func main() {
  9. cmd := exec.Command("%path to app%\\ConsoleApp.exe") // process that will be started
  10. stdout, err := cmd.StdoutPipe() // use std out pipe
  11. if err != nil {
  12. log.Fatal(err)
  13. }
  14. stdin, err := cmd.StdinPipe() // use std in pipe
  15. if err != nil {
  16. log.Fatal(err)
  17. }
  18. if err := cmd.Start(); err != nil { // start
  19. log.Fatal(err)
  20. }
  21. for true {
  22. var w1 string
  23. _, err := fmt.Scanln(&w1) // read line
  24. if err != nil {
  25. log.Fatal()
  26. }
  27. go func() {
  28. io.WriteString(stdin, w1) // pass it to console app
  29. }()
  30. read, err := io.ReadAll(stdout) // read result
  31. fmt.Println(read)
  32. if err != nil {
  33. log.Fatal()
  34. }
  35. }
  36. }


我开始调试控制台应用程序的进程(它出现在任务管理器中,RMC -),但有符号错误,所以我甚至不能理解我的应用程序是否得到字符串或没有。
这只是我麻烦的一半。我想有一两次我的控制台应用程序得到了字符串(我的意思是在以前的时间),但只有第一次,导致管道关闭后,传输/复制它。那么我如何控制这一点?我想做几个事务,写和读,并关闭管道只有当我需要它。

编辑:我对ConsoleApp做了一点修改,现在看起来是这样的:

  1. double sum = 0;
  2. bool flag = true;
  3. while(flag) {
  4. var str = Console.ReadLine();
  5. double addend;
  6. flag = double.TryParse(str, out addend);
  7. // File creation will indicate that message was recieved.
  8. using(StreamWriter writer = new StreamWriter("t.txt")) {
  9. writer.WriteLine($"{flag}");
  10. }
  11. sum += flag ? addend : 0;
  12. Console.WriteLine(sum);
  13. }
  14. return 0;

hsgswve4

hsgswve41#

做了一些修改,正如@Burak指出的,ReadAll将停止执行,直到进程退出,所以不要认为你想要这样。我还使用了bufio.Scanner来读取每行:

  1. // You can edit this code!
  2. // Click here and start typing.
  3. package main
  4. import (
  5. "bufio"
  6. "fmt"
  7. "io"
  8. "os/exec"
  9. )
  10. func main() {
  11. cmd := exec.Command("%path to app%\\ConsoleApp.exe") // process that will be started
  12. stdout, err := cmd.StdoutPipe() // use std out pipe
  13. if err != nil {
  14. panic(err)
  15. }
  16. scanner := bufio.NewScanner(stdout)
  17. stdin, err := cmd.StdinPipe() // use std in pipe
  18. if err != nil {
  19. panic(err)
  20. }
  21. if err := cmd.Start(); err != nil { // start
  22. panic(err)
  23. }
  24. for {
  25. var w1 string
  26. _, err := fmt.Scanln(&w1) // read line from console
  27. if err != nil {
  28. panic(err)
  29. }
  30. if _, err := io.WriteString(stdin, w1); err != nil {
  31. panic(err)
  32. } // pass it to console app
  33. if scanner.Scan() {
  34. read := scanner.Text()
  35. fmt.Println(read)
  36. } else {
  37. if err := scanner.Err(); err != nil {
  38. panic(err)
  39. }
  40. }
  41. }
  42. }

字符串

展开查看全部
jjjwad0x

jjjwad0x2#

所以,@maxm真的很接近(或者甚至已经得到了解决方案,但它对我不起作用,fsr)。
go部分:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os/exec"
  7. )
  8. func main() {
  9. cmd := exec.Command("%path to the exe%")
  10. stdout, err := cmd.StdoutPipe()
  11. if err != nil {
  12. log.Fatal(err)
  13. }
  14. stderr, err := cmd.StderrPipe()
  15. if err != nil {
  16. log.Fatal(err)
  17. }
  18. scanner := bufio.NewScanner(stdout)
  19. stdin, err := cmd.StdinPipe()
  20. if err != nil {
  21. log.Fatal(err)
  22. }
  23. if err := cmd.Start(); err != nil {
  24. log.Fatal(err)
  25. }
  26. for {
  27. var w1 string
  28. _, err := fmt.Scanln(&w1)
  29. w2 := []byte(w1) // important! You need convert string to byte array
  30. if err != nil {
  31. log.Fatal()
  32. }
  33. if _, err := stdin.Write(w2); err != nil { // pass byte array
  34. log.Fatal(stderr)
  35. panic(err)
  36. }
  37. if scanner.Scan() {
  38. read := scanner.Text()
  39. fmt.Println(read)
  40. } else {
  41. if err := scanner.Err(); err != nil {
  42. panic(err)
  43. }
  44. }
  45. }
  46. }

字符串
C#部分很简单。首先你需要从字节数组中恢复字符串:

  1. public static string ByteArrayToString(this byte[] byteArray, int size) {
  2. // get decoder to decode input encoding
  3. var decoder = Console.InputEncoding.GetDecoder();
  4. // count char that will be restored
  5. int charCount = decoder.GetCharCount(byteArray, 0, size);
  6. // initialize char array
  7. char[] charArray = new char[charCount];
  8. // restore to char array
  9. decoder.GetChars(byteArray, 0, size, charArray, 0);
  10. // get and return string from our char array
  11. return new string(charArray);
  12. }


主要部分是下一个:

  1. double sum = 0;
  2. bool flag = true;
  3. while(flag) {
  4. string str;
  5. using Stream stdin = Console.OpenStandardInput(); // for reading
  6. byte[] buffer = new byte[2048];
  7. int bytes = 0; // bytes count
  8. while((bytes = stdin.Read(buffer, 0, buffer.Length)) > 0) { // read
  9. str = buffer.ByteArrayToString(bytes); // restore string
  10. flag = double.TryParse(str, out double addend);
  11. sum += flag ? addend : 0;
  12. Console.WriteLine(sum); //write
  13. if(!flag)
  14. break;
  15. }
  16. }
  17. return 0;

展开查看全部

相关问题