0

For educational purposes at the university, I am developing a modular WCF C# application. The client app sends a source, the server takes care of compiling, testing and returning a result to the client.

One of the modules of the server does the compiling job. It consumes the source and produces an EXE to be used by the other module(s).

My problem is: when invoking cl.exe for the case when the given source is written in C++, I manage to compile it, but the compiling module cannot receive the error messages properly from the child process, that runs cmd.exe, which then starts cl.exe. The source code and an example of what actually happens say more than a million words, so here they are:

public static string clPath = @"E:\path_to_project\Client\clTo4kaEXE\";
string sourceCode = "//given source";
using (StreamWriter sw = new StreamWriter(clPath + exeName + ".cpp"))
{
    sw.Write(sourceCode);
    sw.Flush();
}

Process clTo4kaEXE = new Process();
clTo4kaEXE.StartInfo.FileName = clPath + "cmd.exe";
clTo4kaEXE.StartInfo.WorkingDirectory = clPath;
clTo4kaEXE.StartInfo.UseShellExecute = false;
clTo4kaEXE.StartInfo.RedirectStandardOutput = true;
clTo4kaEXE.StartInfo.RedirectStandardError = true;
clTo4kaEXE.StartInfo.RedirectStandardInput = true;
clTo4kaEXE.StartInfo.Arguments = "%comspec% /k \"\"e:\\vs2010\\VC\\vcvarsall.bat\"\" x86"; 

clTo4kaEXE.Start();
clTo4kaEXE.StandardInput.WriteLine("cl /EHsc " + exeName + ".cpp");
StreamReader clStandardOutput = clTo4kaEXE.StandardOutput;
StreamReader clErrorOutput = clTo4kaEXE.StandardError;
string clStdOutput = "";
string temp = "";
while(true)
{
    //Debugger.Launch(); // breakpoint
    temp = clStandardOutput.ReadLine();
    Console.WriteLine("STD TEMP = {0}", temp);
    clStdOutput += temp;
    //if (temp == null /*|| temp == "" */|| clStandardOutput.EndOfStream)
    //{
    //    break;
    //}
    if (clStandardOutput.Peek() == -1 && temp == "")
    {
        break;
    }
}

string clErrOutput = "";
temp = "";
while (true)
{
    temp = clErrorOutput.ReadLine();
    Console.WriteLine("ERROR TEMP = {0}", temp);
    clErrOutput += temp;
    //if (temp == null || temp == "" || clErrorOutput.EndOfStream)
    //{
    //    break;
    //}
    if (clErrorOutput.Peek() == -1 && temp == "")
    {
        break;
    }
}

clTo4kaEXE.Close();

Console.WriteLine("[Modul_Compile] cl.exe returned on its standard output: {0}\n", clStdOutput);
Console.WriteLine("[Modul_Compile] cl.exe returned on its error output: {0}\n", clErrOutput);

When there is an error in the source, for example missing ';' somewhere, then here is what i see in the console:

Console contents screenshot

Then I decided to run Visual Studio Command Prompt giving it the same source code and here is what i get:

enter image description here

Remarks:

  1. clStdOutput= clStandardOutput.ReadToEnd(); used instead of that while(true){} causes the client app's window to "freeze" and the compiling module doesn't receive anything from its child process.

  2. I am pretty surprised that cl.exe prints the messages "Microsoft (R) 32-bit C/C++ Optimizing..." and "Copyright (C)... All rights reserved." to its Error output - the stream, from which I expect to receive the compiling error.

  3. I searched the net for any info, found some clues, which helped me get anything from the child process. Now the next step is to get what i need to.

  4. I couldn't find a way to start the VS Command Prompt, because it's actually a shortcut, not pointing to an exe, so I couldn't benefit from it.

Any help would be appreciated! Thanks! :)

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
user2177283
  • 281
  • 1
  • 4
  • 19
  • Is there an 'edit' button available and I cannot find it, or...? (I see that for comments, there is one) Anyway, I forgot to mention, that exeName is just a name, which doesn't include the .exe extension. It is because i expect to get exeName.exe when compiling exeName.cpp – user2177283 Nov 15 '15 at 21:07
  • (It's under the tags below the question). Your `peek` isn't the right way to check for the termination of the executable. There's some time elapsing between printing the copyright and finding the first parse error. – Kenney Nov 15 '15 at 21:07
  • You are not going to get far with this code. The smart way to do this is to keep it as simple as possible. Generate a .bat file with all the commands and ask cmd.exe to run it and redirect all output to a file. [Hints here](http://stackoverflow.com/a/20789248/17034). – Hans Passant Nov 15 '15 at 21:20
  • "I couldn't find a way to start the VS Command Prompt, because it's actually a shortcut, not pointing to an exe, so I couldn't benefit from it." You know you can get the shortcut target path. Also C# has libraries built in the get the location of the VS installation folder. You can use that as a base directory to locate cl.exe and run it directly. – CodingMadeEasy Nov 16 '15 at 01:16
  • I would like to say one big THANK YOU all for your quick and useful pieces of advice! :) I managed to solve my problem using the Hans Passant's idea - to redirect both StandardOutput and ErrorOutput to a file output.txt like this: Instead of clTo4kaEXE.StandardInput.WriteLine("cl /EHsc " + exeName + ".cpp"); I wrote clTo4kaEXE.StandardInput.WriteLine("cl /EHsc " + exeName + ".cpp 1> output.txt 2>&1"); – user2177283 Nov 16 '15 at 18:54

0 Answers0