1

My problem is that I won't get the same result when running a command from command-line manually, or if I run it in C# I try to convert an .odt file to .rst (reStructuredText) and therefore I got the right tool, which works perfectly when I do it on my own: just send the command in cmd: "odt2rst.py input.odt output.rst" But when I try the same from code, it won't work. Sometimes it times out, sometimes it starts but does not finish. I mean I got half of the output.rst, simply cut in the middle or somewhere. I attach my C# code, if You could see something that I did wrong, please let me know; or as you got any kind if solutions.

System.Diagnostics.Process process = new System.Diagnostics.Process();
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
            startInfo.FileName = "cmd.exe";
            startInfo.WorkingDirectory = txt_output.Text;
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardOutput = true;
            startInfo.RedirectStandardInput = true;
            startInfo.RedirectStandardError = true;
            process.StartInfo = startInfo;
            process.Start();

        process.StandardInput.WriteLine(@"odt2rst.py input.odt uncut.rst");
        StreamReader k = new StreamReader(process.StandardOutput.BaseStream);
        StreamReader l = new StreamReader(process.StandardError.BaseStream);
        process.StandardInput.WriteLine(@"exit");
        MessageBox.Show(k.ReadToEnd());
        MessageBox.Show(l.ReadToEnd());

In the Messageboxes I see it starts working, but it just simply closes in the middle.

Thanks for your help!

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
akoswadd
  • 11
  • 2

2 Answers2

1

Problem is flushing, data isn't actually sent between processes. Standard output flushing happens differently depending on if you run the program on interactive terminal or not.

After this line:

process.StandardInput.WriteLine(@"exit");

Try adding this:

process.StandardInput.Flush();

If that is not enough, then problem is on the script side flushing, try adding flushing to your Python script, after it has produced all output. Or you can also use setvbuf. This SO answer has more about this.


If problems persist, it'd be best if you can make the script to have a non-interactive mode too. It could perhaps be enabled with extra command line switch if interactive operation is needed for other use. So then the script would just do the given conversion and exit, without ever reading anything from standard input. That way you wouldn't need to care about flushing or anything, everything would be flushed when script exits. This has the downside of slowing things down, if you need to do many conversions, because starting a process, especially a big thing like Python interpreter, can take a bit of time.

Community
  • 1
  • 1
hyde
  • 60,639
  • 21
  • 115
  • 176
  • I appriciate your help but unfortunately they did not work. I hoped that the standardinput flush will work, but somehow it did not, it just cuts the output in half as well. On the other hand, i tried flushing my python script (i must admit that my python skills are not the best) but it also failed. And if there would be a problem with the python script, could I run it manually ? – akoswadd Jun 02 '14 at 12:52
  • Well, one possiblity is, that the Python script (not written by you, I take it?) works asynchronously, and obeys that `exit` before it has processed all data. If possible, I'd make the whole script non-interactive (with an extra command line argument maybe), so it will just do the single conversion and exit by itself when done. – hyde Jun 02 '14 at 13:06
  • yes that sounds actually what I thought at first. However, I broke the code with a process.WaitForExit() and I manually closed it when I saw it is not computing anymore. Stayed the same :( I link you the .py I use: https://github.com/jimklo/odt2rst/blob/master/odt2rst.py Thanks for your time! edit: I'm afraid when I run it from C# it is not able to handle all the error messages. Is it possible? I mean at the point it always stops, I get some kind of 'Warn' when doing it manually, but it moves on, and even converts that part as well. – akoswadd Jun 02 '14 at 13:09
  • Try adding a bit of sleep between the conversion command and the exit command. Also add flush after the conversion command (and the sleep). Just to see what happens then... – hyde Jun 02 '14 at 13:13
  • I did the sleep thing (3 seconds). It finishes after 1 second, and just stays there for 2 more seconds doing nothing, so I really think there must be something with handling that error, but I have no idea why. It must just write it out and go on. What does it do different when i run it manually or not? – akoswadd Jun 02 '14 at 13:20
  • I really think the python 'printed' error msgs cannot be shown. Im almost a hundred percent sure it is the reason. Anyway: I have no solution yet. – akoswadd Jun 02 '14 at 13:29
  • Next step I think is, implement proper asynchronous reading of both stdout and stderr in C#. It may be that process or OS buffers become full and block otherwise. – hyde Jun 02 '14 at 16:30
0

I had problems with the Python code itself. I got it from Codeproject and it is still in Beta phrase, therefore it is not perfect. I still have no clue why is it different when executing from cmdline or automatized-cmdline, but I managed to fix it by modifying the Python code. Unfortunately none of the comments helped, but thank you very much for your time, I really appreciate it!

akoswadd
  • 11
  • 2