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;
}
}