Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
DotNet
acad.assignment.mngr
academic
adonet
aspnet
aspnet.announcements
aspnet.build.controls
aspnet.caching
aspnet.datagridcontrol
aspnet.mobile
aspnet.security
aspnet.webcontrols
aspnet.webservices
clr
compactframework
component_services
datatools
distributed_apps
drawing
faqs
framework
framework.wmi
general
internationalization
interop
languages.csharp
languages.jscript
languages.vb
languages.vb.controls
languages.vb.data
languages.vb.upgrade
languages.vc
languages.vc.libraries
myservices
odbcnet
performance
remoting
scripting
sdk
security
setup
vjsharp
vsa
webservi.enhancements
webservices
windowsforms
windowsforms.controls
winforms.databinding
winforms.designtime
xml
  
 
date: Thu, 17 Jul 2008 15:37:01 -0700 (PDT),    group: microsoft.public.dotnet.languages.csharp        back       


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?
date: Thu, 17 Jul 2008 15:37:01 -0700 (PDT)   author:   not_a_commie

Re: dllimport stdout gets eaten   
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
date: Thu, 17 Jul 2008 19:52:39 -0400   author:   Arne Vajhøj

Re: dllimport stdout gets eaten   
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
date: Fri, 18 Jul 2008 09:06:49 -0500   author:   Ben Voigt [C++ MVP] am

Re: dllimport stdout gets eaten   
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
date: Fri, 18 Jul 2008 20:25:45 -0400   author:   Arne Vajhøj

Re: dllimport stdout gets eaten   
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();
		}

	}
}
date: Mon, 21 Jul 2008 08:26:27 -0700 (PDT)   author:   not_a_commie

Re: dllimport stdout gets eaten   
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
date: Mon, 21 Jul 2008 13:46:15 -0500   author:   Ben Voigt [C++ MVP] am

Re: dllimport stdout gets eaten   
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
date: Sun, 27 Jul 2008 21:30:40 -0400   author:   Arne Vajhøj

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us