C
C#4d ago
Abdesol

standard output from Process not giving any output for certain commands

I am using C# process to run some processes. The shell is cmd.exe, and running several types of scripts work. But, when I try to run python idle with the command cmd.exe /C python, it is giving no output and the process is also not exiting. It should have displayed the idle texts like it do on a normal terminal. The task function in which I am writing the output:
async Task OutputToConsole(StreamReader reader, Process process)
{
var buffer = new char[128];
while (true)
{
var read = await reader.ReadAsync(buffer, 0, buffer.Length);
if (read > 0)
{
var output = new string(buffer, 0, read);
Console.Write(output);
}

if (process.HasExited && read == 0) break;
}
}
async Task OutputToConsole(StreamReader reader, Process process)
{
var buffer = new char[128];
while (true)
{
var read = await reader.ReadAsync(buffer, 0, buffer.Length);
if (read > 0)
{
var output = new string(buffer, 0, read);
Console.Write(output);
}

if (process.HasExited && read == 0) break;
}
}
Is my approach wrong? Thank you!
54 Replies
SparkyCracked
SparkyCracked4d ago
Hey @Abdesol When you run 'python' from cmd.exe, it typically starts Python in the interactive mode if you're in the terminal but may behave differently when started from another process like through C#. So just make sure you calling the right executable. Another option if the above doesn't work is just to redirect the input and output and potentially the error streams. Your method for reading the output looks correct from my stance, just make sure there is output to be read though
Abdesol
Abdesol4d ago
I think that is the problem as well.. running python.exe is not giving any output, maybe cuz it is interactive but powershell works, but when I run wsl, I don't get the first color full part of it.. I mean the path of files is some how colorful and it is not being captured by the program I am redirecting the error as well.. it uses this function and runs on a separate task
Abdesol
Abdesol4d ago
but it doesn't look interactive to me
No description
SparkyCracked
SparkyCracked4d ago
Ok wait, I am not sure what your goal is here @Abdesol
Abdesol
Abdesol4d ago
I am basically building a simple terminal. I have got many things sorted out, but the problems now are: 1. python and some commands are not giving output at all 2. some commands like "git clone", which show progress on the same line of console, instead of a new line, I am not able to capture those lines
SparkyCracked
SparkyCracked4d ago
If you wanna run python scripts, you can run the a file with the script in it...if you wanna see colors then emulating a terminal will help
Abdesol
Abdesol4d ago
with files/scripts, it works well, I know handling an interactive processes in a simple terminal project is not going to go easily but that python doesn't look interactive.. the main problem right now is the second one here
SparkyCracked
SparkyCracked4d ago
Yeah it would, because you running python the way a user will logically speaking
Abdesol
Abdesol4d ago
yeah, there is no actual need to run the idle
SparkyCracked
SparkyCracked4d ago
It will run python code...and has it's set of memory. If you open cmd and type python, then create variables and print them it will show output
Abdesol
Abdesol4d ago
yeah, on cmd and powershell it works, it is just not working in my code
Abdesol
Abdesol4d ago
this is my terminal and it is stuck like this when I run the python command
No description
SparkyCracked
SparkyCracked4d ago
But going back to your core issues. For interactive commands like Python, the issue is often related to the command's environment detection. Python, when launched in interactive mode, expects an interactive terminal. When it detects that it is not attached to an interactive terminal (like when standard output is redirected in a C# Process), it might behave differently Try running python scripts in non-interactive modes, you can execute the scripts with predefined inputs, or using -c command to execute a piece of python code. Additionally you can look into 'pseudo-terminal'. It's a little complex in windows but can be partially simulated using third party libraries like wimpty or something names 'Console Terminal' (I forgot it's name but something like that).
Abdesol
Abdesol4d ago
ah, interesting, I understand the problem now.. but for the second issue, what do you have to say about it? like when running a git clone command, it doesn't go beyond this, but it is actually doing the job and did actually clone it
Abdesol
Abdesol4d ago
it finishes just like his
No description
SparkyCracked
SparkyCracked4d ago
With regards to git clone, commands like that output progress dynamically by rewriting lines. It uses \r as carriage returns intend of \n and some standard output redirects may not handle that well. So you can either read raw output (which I like to do most of the time) and when you detect \r then treat it as an instruction to overwrite the current line in your output display. busy typing lol, I take some time give me a minute lol.
Abdesol
Abdesol4d ago
hehe, thank you 😅 let me try to remove any /r from the output provided and see if it prints everything first not working this way
SparkyCracked
SparkyCracked4d ago
For the git I can give you some code as I have done this before:
c#
StringBuilder currentLine = new StringBuilder();
while (!reader.EndOfStream || !process.HasExited)
{
int c = reader.Read();
if (c == -1) { if (process.HasExited) break; else continue; }

char ch = (char)c;
if (ch == '\r') {
Console.Write(currentLine.ToString());
Console.Write('\r');
currentLine.Clear();
} else if (ch == '\n') {
Console.WriteLine(currentLine.ToString());
currentLine.Clear();
} else {
currentLine.Append(ch);
}
}
if (currentLine.Length > 0)
Console.WriteLine(currentLine.ToString());
c#
StringBuilder currentLine = new StringBuilder();
while (!reader.EndOfStream || !process.HasExited)
{
int c = reader.Read();
if (c == -1) { if (process.HasExited) break; else continue; }

char ch = (char)c;
if (ch == '\r') {
Console.Write(currentLine.ToString());
Console.Write('\r');
currentLine.Clear();
} else if (ch == '\n') {
Console.WriteLine(currentLine.ToString());
currentLine.Clear();
} else {
currentLine.Append(ch);
}
}
if (currentLine.Length > 0)
Console.WriteLine(currentLine.ToString());
So you basically checking characters and when it finds the \r it will then reset the line buffer.
Abdesol
Abdesol4d ago
oh interesting.. let me check it rq
Abdesol
Abdesol4d ago
@SparkyCracked even with your code, by replacing it above in my function, I faced the same issue again
No description
Abdesol
Abdesol4d ago
I tried adding Console.WriteLine("Here") in the if condition and it was not printing that.. I think there was no /r text ig
SparkyCracked
SparkyCracked4d ago
Yeah...tough. Are you able to get the raw outputs? Put a break and see what the variables are
Abdesol
Abdesol4d ago
okay weird problem after it finished the first line i.e. Clonning into 'My-Website'...
SparkyCracked
SparkyCracked4d ago
It just ended?
Abdesol
Abdesol4d ago
EndOfStream got to tru
No description
Abdesol
Abdesol4d ago
yep
async Task ExecuteCommand(string command, string workingDirectory)
{
try
{
var processStartInfo = new ProcessStartInfo
{
FileName = shell,
Arguments = commandPrefix + command + commandSuffix,
WorkingDirectory = workingDirectory,
RedirectStandardOutput = true,
RedirectStandardInput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};

using var process = new Process();
process.StartInfo = processStartInfo;
process.Start();

var outputTask = OutputToConsole(process.StandardOutput, process);
var errorTask = OutputToConsole(process.StandardError, process);
var inputTask = InputToProcess(process);

await process.WaitForExitAsync();

await Task.WhenAll(outputTask, errorTask, inputTask);
}
catch (Exception e)
{
Console.WriteLine($"ErrorN: {e}");
}
}
async Task ExecuteCommand(string command, string workingDirectory)
{
try
{
var processStartInfo = new ProcessStartInfo
{
FileName = shell,
Arguments = commandPrefix + command + commandSuffix,
WorkingDirectory = workingDirectory,
RedirectStandardOutput = true,
RedirectStandardInput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};

using var process = new Process();
process.StartInfo = processStartInfo;
process.Start();

var outputTask = OutputToConsole(process.StandardOutput, process);
var errorTask = OutputToConsole(process.StandardError, process);
var inputTask = InputToProcess(process);

await process.WaitForExitAsync();

await Task.WhenAll(outputTask, errorTask, inputTask);
}
catch (Exception e)
{
Console.WriteLine($"ErrorN: {e}");
}
}
this is the function where I am dealing with the process and the tasks.. is there anything I am missing here?
SparkyCracked
SparkyCracked4d ago
It looks fine from my side, I don't see any issues
Abdesol
Abdesol4d ago
for windows no suffix, and the prefix is /C and shell is cmd.exe
SparkyCracked
SparkyCracked4d ago
There might be a potential race condition where the process exits before all output has been read. To mitigate this, consider awaiting the I/O tasks before awaiting process.WaitForExitAsync(). This ensures that all output is captured even if the process exits quickly:
c#
var outputTask = OutputToConsole(process.StandardOutput, process);
var errorTask = OutputToConsole(process.StandardError, process);
var inputTask = InputToProcess(process);

await Task.WhenAll(outputTask, errorTask, inputTask);
await process.WaitForExitAsync();
c#
var outputTask = OutputToConsole(process.StandardOutput, process);
var errorTask = OutputToConsole(process.StandardError, process);
var inputTask = InputToProcess(process);

await Task.WhenAll(outputTask, errorTask, inputTask);
await process.WaitForExitAsync();
Abdesol
Abdesol4d ago
oh, interesting.. let me check rq
SparkyCracked
SparkyCracked4d ago
Here is some documentation on race conditions
Race conditions and deadlocks - Visual Basic
This article describes that Visual Basic offers the ability to use threads in Visual Basic applications for the first time. Threads introduce debugging issues such as race conditions and deadlocks.
SparkyCracked
SparkyCracked4d ago
I've recently been diving deep into tasks and threading so yeah
Abdesol
Abdesol4d ago
okay will check it out
Abdesol
Abdesol4d ago
I tried putting a console write line outside the while loop and the problem is still around
No description
Abdesol
Abdesol4d ago
the first one is from the error output, and the second one is from the actual output actually, I just checked and the error task is the one responsible for the git clone output
SparkyCracked
SparkyCracked4d ago
For me I want to see if you ever have more than that one in your code at any point. So when you step in your code, once you print out 'Cloning into...' hover over the variable and see what it's contents are
Abdesol
Abdesol4d ago
may I share the code? it is just a one file code
SparkyCracked
SparkyCracked4d ago
Ohh fair, if you comfortable with that...
Abdesol
Abdesol4d ago
yeah, I will probably make this simple terminal public if it gets to work well what was the way to share it? binpath? could you share the link
SparkyCracked
SparkyCracked4d ago
$code
MODiX
MODiX4d ago
To post C# code type the following: ```cs // code here ``` Get an example by typing $codegif in chat For longer snippets, use: https://paste.mod.gg/
SparkyCracked
SparkyCracked4d ago
You can use the above link
Abdesol
Abdesol4d ago
BlazeBin - bzkdrnmwuvvs
A tool for sharing your source code with the world!
Abdesol
Abdesol4d ago
@SparkyCracked sorry not this one ig
Abdesol
Abdesol4d ago
BlazeBin - mxifcyrdlkeu
A tool for sharing your source code with the world!
Abdesol
Abdesol4d ago
that is the old one
SparkyCracked
SparkyCracked4d ago
Ok cool
Abdesol
Abdesol4d ago
btw, you have to click enter to get back to the path part that is an issue for later
SparkyCracked
SparkyCracked4d ago
@Abdesol Some progress... I've located a potential issue where the output capturing from the process in C# is not handling the asynchronous nature of the git clone operation correctly. It's super weird so I am gonna try see if I can read the outputs properly and prevent early termination of the process (I mean git still clones cause my massive project managed to clone so it works which is good)
Abdesol
Abdesol4d ago
great! and yeah, it does actually clone, just doesn't show the progress bar and the lines that come after that
SparkyCracked
SparkyCracked4d ago
Ok @Abdesol I can't lie, it may take me some time to figure this out. I managed to get it to the point where it exits the cloning process when done and waits for input again by itself but the actual printing of output is a little tougher. I don't understand the reason it is bombing out as of yet
Abdesol
Abdesol3d ago
ah, I really appreciate your cooperation and absolutely no rush @SparkyCracked Sup, any progress?
SparkyCracked
SparkyCracked3d ago
Yoo wassup i capped myself to 45 min yesterday on working on it, still at the same place. Will look into it today again.
Abdesol
Abdesol2d ago
okay, tnx