473,223 Members | 1,720 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,223 software developers and data experts.

dllimport stdout gets eaten

I changed the stdout in my C# app using Console.SetOut. It works fine
for all my Console.Out.Write calls and with log4net. However, I don't
see any output from native dlls that write to stdout. What am I doing
wrong?
Jul 17 '08 #1
6 5147
not_a_commie wrote:
I changed the stdout in my C# app using Console.SetOut. It works fine
for all my Console.Out.Write calls and with log4net. However, I don't
see any output from native dlls that write to stdout. What am I doing
wrong?
Nothing.

Why should changing something inside the Console class
change what some native code does ?

You need to do something in your native code to
get output where you want it.

Arne
Jul 17 '08 #2
Arne Vajhøj wrote:
not_a_commie wrote:
>I changed the stdout in my C# app using Console.SetOut. It works fine
for all my Console.Out.Write calls and with log4net. However, I don't
see any output from native dlls that write to stdout. What am I doing
wrong?

Nothing.

Why should changing something inside the Console class
change what some native code does ?
If for example, that managed code was a wrapper around SetStdHandle. But
it's not, it changes Console.Out rather than changing stdout underneath.
>
You need to do something in your native code to
get output where you want it.
SetStdHandle, most likely. And then it doesn't have to be a change to the
native code, as long as it's called from the same process.
>
Arne

Jul 18 '08 #3
Ben Voigt [C++ MVP] wrote:
Arne Vajhøj wrote:
>not_a_commie wrote:
>>I changed the stdout in my C# app using Console.SetOut. It works fine
for all my Console.Out.Write calls and with log4net. However, I don't
see any output from native dlls that write to stdout. What am I doing
wrong?
Nothing.

Why should changing something inside the Console class
change what some native code does ?

If for example, that managed code was a wrapper around SetStdHandle. But
it's not, it changes Console.Out rather than changing stdout underneath.
I can not see how it could be a wrapper around SetStdHandle. Out is a
TextWriter. If I write my own class that extends TextWriter and call
SetOut with it. There are no handle to pass to native and no way
for the native code to call my class.
>You need to do something in your native code to
get output where you want it.

SetStdHandle, most likely. And then it doesn't have to be a change to the
native code, as long as it's called from the same process.
I was thinking freopen, but if it is documented that SetStdHandle
interacts "nicely" with the C RTL, then that can obviously be
used.

Arne
Jul 19 '08 #4
I got this to work. The setvbuf is critical. Here's my test code.
First, the dll:

#include <stdio.h>

__declspec(dllexport) void PrintMsg();

void PrintMsg()
{
setvbuf(stdout, NULL, _IONBF, 0);
printf("blah blah blah\n");
}

Second, the C# code:

using System;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Controls;

namespace TestPrintf
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
protected static extern bool SetStdHandle(int nStdHandle, IntPtr
hConsoleOutput);

[DllImport("PrintDll.dll", CallingConvention =
CallingConvention.Cdecl)]
protected static extern void PrintMsg();

[STAThread]
public static void Main(string[] args)
{
var id = Process.GetCurrentProcess().Id; // make this instance
unique
var serverPipe = new NamedPipeServerStream("consoleRedirect" + id,
PipeDirection.In, 1);
var clientPipe = new NamedPipeClientStream(".", "consoleRedirect" +
id, PipeDirection.Out, PipeOptions.WriteThrough);
ThreadPool.QueueUserWorkItem(state =>
{
serverPipe.WaitForConnection();
using (var stm = new StreamReader(serverPipe))
{
while (serverPipe.IsConnected)
{
try
{
var txt = stm.ReadLine();
if (!string.IsNullOrEmpty(txt))
MessageBox.Show("Got stdout with: " + txt);
}
catch (IOException)
{
break; // normal disconnect
}
}
}
}, null);
clientPipe.Connect();
var hr11 = new HandleRef(clientPipe,
clientPipe.SafePipeHandle.DangerousGetHandle());
SetStdHandle(-11, hr11.Handle); // redirect stdout to my pipe
var app = new Application();
var win = new Window { Width = 300, Height = 200 };
var sp = new StackPanel { Orientation = Orientation.Horizontal };
win.Content = sp;
var b1 = new Button { Content = "Direct", Width = 100 };
sp.Children.Add(b1);
var b2 = new Button { Content = "Indirect", Width = 100 };
sp.Children.Add(b2);
var b3 = new Button { Content = "DllImport", Width = 100 };
sp.Children.Add(b3);

b1.Click += (sender, e) =Console.Out.WriteLine("Direct Button was
clicked");
b2.Click += (sender, e) =>
{
using (var stdout = Console.OpenStandardOutput())
{
var bytes = Console.OutputEncoding.GetBytes("Indirect Button
was clicked" + Console.Out.NewLine);
stdout.Write(bytes, 0, bytes.Length);
}
};
b3.Click += (sender, e) =PrintMsg();

app.Run(win);
clientPipe.Dispose();
serverPipe.Dispose();
}

}
}
Jul 21 '08 #5
Arne Vajhøj wrote:
Ben Voigt [C++ MVP] wrote:
>Arne Vajhøj wrote:
>>not_a_commie wrote:
I changed the stdout in my C# app using Console.SetOut. It works
fine for all my Console.Out.Write calls and with log4net. However,
I don't see any output from native dlls that write to stdout. What
am I doing wrong?
Nothing.

Why should changing something inside the Console class
change what some native code does ?

If for example, that managed code was a wrapper around SetStdHandle.
But it's not, it changes Console.Out rather than changing stdout
underneath.

I can not see how it could be a wrapper around SetStdHandle. Out is a
TextWriter. If I write my own class that extends TextWriter and call
SetOut with it. There are no handle to pass to native and no way
for the native code to call my class.
I agree. I was just trying to show that it wasn't an entirely unreasonable
expectation though, by mentioning a function that would behave as the OP
expected. And, as you point out, it is limited to redirecting to an OS
handle, not an arbitrary TextWriter.
>
>>You need to do something in your native code to
get output where you want it.

SetStdHandle, most likely. And then it doesn't have to be a change
to the native code, as long as it's called from the same process.

I was thinking freopen, but if it is documented that SetStdHandle
interacts "nicely" with the C RTL, then that can obviously be
used.
I didn't see any assurance that the native code was written in C, or that
the OP knew which RTL was being used. If the DLL was statically linked, it
would be next-thing-to-impossible to call the "right" freopen.
>
Arne

Jul 21 '08 #6
Ben Voigt [C++ MVP] wrote:
Arne Vajhøj wrote:
>Ben Voigt [C++ MVP] wrote:
>>Arne Vajhøj wrote:
You need to do something in your native code to
get output where you want it.
SetStdHandle, most likely. And then it doesn't have to be a change
to the native code, as long as it's called from the same process.
I was thinking freopen, but if it is documented that SetStdHandle
interacts "nicely" with the C RTL, then that can obviously be
used.

I didn't see any assurance that the native code was written in C, or that
the OP knew which RTL was being used. If the DLL was statically linked, it
would be next-thing-to-impossible to call the "right" freopen.
Good point.

Arne
Jul 28 '08 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Tsai Li Ming | last post by:
Dear all, I have a problem with a redirecting stdout and stderr. I am a top level module and has no control over the imported modules that are making system calls such as os.system or popen2.* ....
7
by: Edward Diener | last post by:
From within a function in my own module I need to take the output from a Python module "A", which is sending data to stdout and which can not be changed and which I need to invoke as a top-level...
0
by: Roman Neuhauser | last post by:
Hello, I have a piece of code that gets run in a script that has its stdout closed: import sys sys.stdout = sys.stderr c = subprocess.Popen (..., stdin = subprocess.PIPE,
1
by: Oz | last post by:
This is long. Bear with me, as I will really go through all the convoluted stuff that shows there is a problem with streams (at least when used to redirect stdout). The basic idea is that my...
4
by: Oz | last post by:
This is long. Bear with me, as I will really go through all the convoluted stuff that shows there is a problem with streams (at least when used to redirect stdout). The basic idea is that my...
0
by: lickspittle | last post by:
Hi, I have Python embedded with my other code, and when my other code opens a console and redirects stdout, stdin and stderr to it, then calls PyRun_InteractiveLoop, it immediately returns with...
15
by: Jim | last post by:
I am extremely frustrated. I am building c# application for a call center and am using a third party API to access some hardware. When develop and test my class using the windows console the...
6
by: Pekka Karjalainen | last post by:
Python 2.4.1 (#1, May 16 2005, 15:19:29) on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from sys import stdout >>> help (stdout.closed) If I do this, it...
20
by: David Mathog | last post by:
A program of mine writes to a tape unit. Output can be either through stdout or through a file opened with fopen(). When all the data is transferred to tape the program needs to close the output...
0
by: VivesProcSPL | last post by:
Obviously, one of the original purposes of SQL is to make data query processing easy. The language uses many English-like terms and syntax in an effort to make it easy to learn, particularly for...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 3 Jan 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). For other local times, please check World Time Buddy In...
0
by: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
0
by: mar23 | last post by:
Here's the situation. I have a form called frmDiceInventory with subform called subfrmDice. The subform's control source is linked to a query called qryDiceInventory. I've been trying to pick up the...
2
by: jimatqsi | last post by:
The boss wants the word "CONFIDENTIAL" overlaying certain reports. He wants it large, slanted across the page, on every page, very light gray, outlined letters, not block letters. I thought Word Art...
0
by: stefan129 | last post by:
Hey forum members, I'm exploring options for SSL certificates for multiple domains. Has anyone had experience with multi-domain SSL certificates? Any recommendations on reliable providers or specific...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.