Console StdOut ans StdErr redirection is only partial. Why and how to redirect full Console output to memory (stream, TextWriter, ...) ?

Eric Ouellet 41 Reputation points
2022-11-01T20:37:55.42+00:00

The problem occur in a WPF application. Console StdOut and StdErr redirection does not works for C++ library, it only works for C# code.

This is code used to redirect in my WPF app:

Outputter = new StreamWriter(@"C:\temp\test.txt");  
Console.SetOut(Outputter);  
Console.SetError(Outputter);  

This code does not show all output data sent to the Console from a C++ dll. Why and how to ensure that everything would be redirected, not only in C# but also in a DLL writen in C++?

Note: If I use this code: accepted answer, then everything is redirected properly in a file, either output from C++ dll. The problem is we don't want a file. We want to redirect directly in a string without a file.

Note: I cannot include the C++ code which is a commercial product.

Sample of output with redirection (WPF app). The ouput is partial compared to console app:

Started
Adding variables ...
Adding constraints ...
Adding objectives ...
Model built, starting optimization ...
x[1,1] = 1

Sample Output when the application is a console application :

Started  
Adding variables ...  
Adding constraints ...  
Adding objectives ...  
Model built, starting optimization ...  
x[1,1] = 1  
n64)  
Thread count: 10 physical cores, 20 logical processors, using up to 20 threads  
Optimize a model with 178554 rows, 106557 columns and 827442 nonzeros  
Model fingerprint: 0xa9efbb41  
Variable types: 54717 continuous, 51840 integer (51840 binary)  
Coefficient statistics:  
  Matrix range     [7e-04, 4e+02]  
  Objective range  [1e-05, 1e+02]  
  Bounds range     [1e+00, 1e+00]  
  RHS range        [1e+00, 3e+03]  
Presolve removed 88855 rows and 45450 columns  
Presolve time: 3.02s  
Presolved: 89699 rows, 61107 columns, 731972 nonzeros  
Variable types: 35340 continuous, 25767 integer (25767 binary)  
  
Deterministic concurrent LP optimizer: primal and dual simplex  
Showing first log only...  
  
  
Root simplex log...  
  
Iteration    Objective       Primal Inf.    Dual Inf.      Time  
   47199    1.7808421e+04   1.021279e+03   1.857243e+09      5s  
Concurrent spin time: 0.00s  
  
Solved with dual simplex  
  
Root relaxation: objective 9.260857e+03, 43881 iterations, 4.73 seconds (6.89 work units)  
  
    Nodes    |    Current Node    |     Objective Bounds      |     Work  
 Expl Unexpl |  Obj  Depth IntInf | Incumbent    BestBd   Gap | It/Node Time  
  
     0     0 9260.85746    0  174          - 9260.85746      -     -    8s  
     0     0 10094.3736    0  436          - 10094.3736      -     -   10s  
     0     0 10094.3778    0  426          - 10094.3778      -     -   11s  
     0     0 10094.3903    0  507          - 10094.3903      -     -   12s  
     0     0 10094.3905    0  508          - 10094.3905      -     -   12s  
     0     0 10094.4241    0  514          - 10094.4241      -     -   14s  
H    0     0                    10195.371156 10094.4241  0.99%     -   14s  
     0     0 10094.4257    0  469 10195.3712 10094.4257  0.99%     -   15s  
     0     0 10094.4298    0  502 10195.3712 10094.4298  0.99%     -   16s  
H    0     0                    10095.583734 10094.4298  0.01%     -   17s  
     0     0 10094.4306    0  510 10095.5837 10094.4306  0.01%     -   17s  
     0     0 10094.4314    0  465 10095.5837 10094.4314  0.01%     -   18s  
     0     0 10094.4314    0   78 10095.5837 10094.4314  0.01%     -   19s  
     0     0 10094.5635    0  271 10095.5837 10094.5635  0.01%     -   19s  
H    0     0                    10095.583277 10094.5635  0.01%     -   19s  
     0     0 10094.5752    0  266 10095.5833 10094.5752  0.01%     -   19s  
H    0     0                    10095.491716 10094.5752  0.01%     -   19s  
     0     0 10094.6001    0  274 10095.4917 10094.6001  0.01%     -   20s  
H    0     0                    10095.396619 10094.6001  0.01%     -   20s  
H    0     0                    10095.176923 10094.6001  0.01%     -   20s  
     0     0 10094.6015    0  278 10095.1769 10094.6015  0.01%     -   20s  
     0     0 10094.6773    0  296 10095.1769 10094.6773  0.00%     -   20s  
     0     0 10094.6773    0  322 10095.1769 10094.6773  0.00%     -   20s  
H    0     0                    10094.999649 10094.6773  0.00%     -   20s  
H    0     0                    10094.999344 10094.6773  0.00%     -   20s  
     0     0 10094.7099    0  325 10094.9993 10094.7099  0.00%     -   20s  
     0     0 10094.7179    0  325 10094.9993 10094.7179  0.00%     -   20s  
     0     2 10094.7179    0  325 10094.9993 10094.7179  0.00%     -   20s  
H   96   114                    10094.990475 10094.7652  0.00%  85.7   21s  
H  249   294                    10094.987654 10094.7689  0.00%  61.1   21s  
*  262   294              36    10094.987402 10094.7689  0.00%  60.8   21s  
*  610   487              27    10094.987173 10094.7711  0.00%  46.5   21s  
H 3825   935                    10094.986106 10094.8707  0.00%  34.6   23s  
  
Cutting planes:  
  Gomory: 21  
  Cover: 18  
  Implied bound: 86  
  MIR: 98  
  Flow cover: 159  
  GUB cover: 1  
  RLT: 62  
  Relax-and-lift: 19  
  
Explored 4580 nodes (198808 simplex iterations) in 23.12 seconds (25.50 work units)  
Thread count was 20 (of 20 available processors)  
  
Solution count 10: 10095 10095 10095 ... 10095.4  
  
Optimal solution found (tolerance 1.00e-05)  
Best objective 1.009498610550e+04, best bound 1.009488620246e+04, gap 0.0010%  
.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,623 questions
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,710 questions
.NET CLI
.NET CLI
A cross-platform toolchain for developing, building, running, and publishing .NET applications.
328 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,625 questions
{count} votes

7 answers

Sort by: Most helpful
  1. Eric Ouellet 41 Reputation points
    2022-11-01T20:51:00.863+00:00

    I can't have a sample. It uses Gurobi Solver which is pretty hard to install and make it works.


  2. Bruce (SqlWork.com) 61,181 Reputation points
    2022-11-01T22:12:54.187+00:00

    when an process is started, StdInput, StdOutput and StdError are file stream handles defined by the creating process see startupinfo

    https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa

    these are windows file (which could be a named pipe) handles . Console, is a .net construct and defaults to these file handles. You can replace its i/o streams wrapping the defaults, but this can not change the defaults as streams do not have file handles. as you have found, the C/C++ library use the defaults.

    you can create a new named pipes that you use instead of the a file for the process redirects in the accepted answer. then wrapping the pipes, you can copy to the Console stream.


  3. Eric Ouellet 41 Reputation points
    2022-11-02T15:34:40.09+00:00

    Can you show me where you found that SetStdHandle use a named pipe handle because I can't find it.
    Also, that would implied a pretty complex solution which should be done in C++ or with lots of pInvoke... Still if possible because we need to be able to notify of changes somewhere.

    0 comments No comments

  4. Bruce (SqlWork.com) 61,181 Reputation points
    2022-11-02T21:19:58.847+00:00

    the process StdInput and StdOutput are handles set by the creating application. with SetStdHandle you can change these handles to any valid i/o handle. when you create a named pipe stream, you can get the handle.

    I'd assume you would create the named pipes in C# as you need read them to pass message to the Console stream you want to set up.

    0 comments No comments

  5. Eric Ouellet 41 Reputation points
    2022-11-03T13:39:41.783+00:00

    Thanks Bruce-SqlWork, I need to track changes in StdOut, not just record it. I need to send event when a change has been received in order to update the user interface with it.
    You have good ideas but some code that show how to do it could really help. Otherwise, it's hard to see everything you have in your mind.

    0 comments No comments