It is solved. Much thanks to @Luuk.
I found what I need while looking at the post he gave and related questions!
Check : Read from location on console C#
Use these (by @Glenn Slayden)
[DllImport("kernel32", SetLastError = true)] static extern IntPtr GetStdHandle(int num); [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ReadConsoleOutputCharacterA( IntPtr hStdout, // result of 'GetStdHandle(-11)' out byte ch, // A̲N̲S̲I̲ character result uint c_in, // (set to '1') uint coord_XY, // screen location to read, X:loword, Y:hiword out uint c_out); // (unwanted, discard) [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ReadConsoleOutputCharacterW( IntPtr hStdout, // result of 'GetStdHandle(-11)' out Char ch, // U̲n̲i̲c̲o̲d̲e̲ character result uint c_in, // (set to '1') uint coord_XY, // screen location to read, X:loword, Y:hiword out uint c_out); // (unwanted, discard)
I was able to read a printed char using code:

Although in this example, only the first char h has been read.
But with this, you will find a way to read all other chars too.
Thus, that's it! Yeah!
OK, but wait, it should be "external console's IO".
Well for this part, the only way I know is that
you could run an independent Console App as the external console app's console.
(Use create Process like what's in the picture in your independent console, or any other better way)
This is a ConsoleReader I made, not pretty, but it works.
class ConsoleReader { [DllImport("kernel32", SetLastError = true)] static extern IntPtr GetStdHandle(int num); [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ReadConsoleOutputCharacterA( IntPtr hStdout, // result of 'GetStdHandle(-11)' out byte ch, // A̲N̲S̲I̲ character result uint c_in, // (set to '1') uint coord_XY, // screen location to read, X:loword, Y:hiword out uint c_out); // (unwanted, discard) [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ReadConsoleOutputCharacterW( IntPtr hStdout, // result of 'GetStdHandle(-11)' out char ch, // U̲n̲i̲c̲o̲d̲e̲ character result uint c_in, // (set to '1') uint coord_XY, // screen location to read, X:loword, Y:hiword out uint c_out); // (unwanted, discard) public static readonly IntPtr stdout = GetStdHandle(-11); public static char? ConsoleUnicodeCharAt(uint x, uint y) { uint coord; coord = x; // loword <-- X coord to read coord |= y << 16; // hiword <-- Y coord to read var success = ReadConsoleOutputCharacterW( stdout, out char ch, // U̲n̲i̲c̲o̲d̲e̲ character result 1, // # of chars to read coord, // (X,Y) screen location to read (see above) out _); // result: actual # of chars (unwanted) if (success) { return ch; } return null; } public static char? ConsoleUnicodeCharAt(uint x, uint y,uint read_char_length) { uint coord; coord = x; // loword <-- X coord to read coord |= y << 16; // hiword <-- Y coord to read var success = ReadConsoleOutputCharacterW( stdout, out char ch, // result: single ANSI char read_char_length, // # of chars to read coord, // (X,Y) screen location to read (see above) out uint actual_char_len); // result: actual # of chars (unwanted) if (success) { return ch; } return null; } public static byte? ConsoleAnsiCharAt(uint x, uint y) { uint coord; coord = x; // loword <-- X coord to read coord |= y << 16; // hiword <-- Y coord to read var success = ReadConsoleOutputCharacterA( stdout, out byte ch, // result: single ANSI char 1, // # of chars to read coord, // (X,Y) screen location to read (see above) out _); // result: actual # of chars (unwanted) if (success) { return ch; } return null; } public static string GetLineAt(uint y, Encoding encoding) { uint i = 0; var line_index = y; if (encoding == Encoding.Unicode) { List<char> line_chars = new List<char>(); char? ch; while ((ch = ConsoleUnicodeCharAt(i++, line_index)) != null) { line_chars.Add((char)ch); if (ch == '\0') { break; } } return new string(line_chars.ToArray()); } else if (encoding == Encoding.ASCII) { List<byte> line_bytes = new List<byte>(); byte? b; while ((b = ConsoleAnsiCharAt(i++, line_index)) != null) { line_bytes.Add((byte)b); if (b == byte.MinValue) { break; } } return Encoding.ASCII.GetString(line_bytes.ToArray()); } else { return null; } } public static string GetLineAt_Unicode(uint y, uint trylength) //trylength is for first char { uint i = 0; var line_index = y; List<char> line_chars = new List<char>(); char? ch; while((ch = ConsoleUnicodeCharAt(i++, line_index, trylength) ).HasValue) { line_chars.Add((char)ch); var size = GetCharSize(ch.Value); i += size - 1; if ((char)ch == '\0') { break; } } return new string(line_chars.ToArray()); } public static string GetCurrentLine(Encoding encoding) { return GetLineAt((uint)Console.GetCursorPosition().Top, encoding); } public static string GetCurrentLine_Unicode(uint try_char_length) { return GetLineAt_Unicode((uint)Console.GetCursorPosition().Top, try_char_length); } public static uint GetCharSize(char c) { var b = BitConverter.GetBytes(c); uint size = (uint)b.Length; for (int i=b.Length-1;i>=0;i--) { if (b[i] != 0) { break; } size--; } return size; } }
Console.IsOutputRedirectedand avoid moving the cursor if it is. You'll also notice that when output is redirected, the cursor position remains at (0, 0), even after writing, so moving it to (-5, 0) is going to fail.mypyexe.exe >c:\temp\py.txt- what if anything ends up in the file