Vesk
Vesk

Reputation: 125

How to change the encoding of a Process's Standard Input in C#?

I am trying to write to the Standard Input of a Process (a C++ program) in C#. The problem is that the C++ program seems to not be able to read what I write from my C# app. Here are both of the programs:

// C#
static void Main(string[] args) {
    Console.InputEncoding = Encoding.Unicode;
    Console.OutputEncoding = Encoding.Unicode;

    Process CoutN = new Process();
    CoutN.StartInfo.FileName = @"C:\Users\Vesk\Desktop\CoutN.exe";
    CoutN.StartInfo.UseShellExecute = false;
    CoutN.StartInfo.RedirectStandardInput = true;
    CoutN.StartInfo.RedirectStandardOutput = false;

    CoutN.Start();
    CoutN.StandardInput.WriteLine("5");

    CoutN.WaitForExit();

    Console.ReadKey();
}
// C++
int main() {
    int n;
    std::cin >> n;
    std::cout << "N is " << n << std::endl;
    return 0;
}

Here is the output from my C# program: N is 0. It should instead be N is 5.

From what I could understand the encoding that C# uses for a Process's Input/Output Stream is the same as the one used by the Console. Here's the thing though, in my C# program I'll need to be able to use the Console to input cyrillic text (as well as other non-ASCII text). The only Console Encoding which seems to work for that is Encoding.Unicode (which apparently is just UTF-16 LE).

But it seems that when I try to write to the Process's Input Stream, it just can't understand that and it outputs N is 0 for some reason. From what I understand this is because UTF-16 is not compatible with ASCII (or whatever the C++ iostream expects).

So is there a way to actually change the Encoding that the Process's Standard Input uses?

Here is what I have tried/cannot try:

StreamWriter str = new StreamWriter(CoutN.StandardInput.BaseStream, Encoding.ASCII);
str.WriteLine("5");

But this didn't work either. I even tried basically all the Encodings and even no Encoding, but nothing worked.

byte[] buffer = Encoding.ASCII.GetBytes("5");
CoutN.StandardInput.BaseStream.Write(buffer, 0, buffer.Length);
CoutN.StandardInput.WriteLine();

And that didn't work.

At this point I feel like I've exhausted all the options that I could try. Any help is appreciated, thanks in advance!

Upvotes: 0

Views: 1184

Answers (1)

PhonicUK
PhonicUK

Reputation: 13864

You don't get to chose what encoding the other process is using from your own code - if you're sending input to the standard input stream of an application that is expecting a specific encoding, then short of it having some setting to change that there's nothing you can do about it.

If you're interacting with the STDIO streams of another application, you are expected to match whatever encoding it is expecting, rather than the other way around. The encoding of the console doesn't really matter except in cases where the application inherits its encoding from the environment.

Indeed, if you're trying to use an encoding that supports Cyrillic characters, then the receiving application must have been designed to accommodate this. If the application was written by someone whose native character set only uses Latin characters then they may well have never bothered to do this. It's part of the reason for the push to adopt UTF8 everywhere since then you don't really need to think about it too much.

Edit: If you're trying to match the expected input encoding, then you do it thusly:

Process.StandardInput.Write(Encoding.ASCII.GetBytes("My String Here\r\n"));

Replacing Encoding.ASCII with whatever character set applies to get the appropriate GetBytes() method.

Note that the ASCII character set specifically does not include Cyrillic characters, so it's impossible to use them in an application that expects ASCII. If it expects some other character set that does support them then you're fine. Cyrillic uses Codepage 855 or needs UTF8.

Upvotes: 1

Related Questions