.net AttachConsole(-1),但Console.WriteLine赢了';输出到父命令提示符?
如果我已将程序设置为.net AttachConsole(-1),但Console.WriteLine赢了';输出到父命令提示符?,.net,winapi,pinvoke,console-application,.net,Winapi,Pinvoke,Console Application,如果我已将程序设置为Windows应用程序,并使用AttachConsole(-1)API,如何获取Console.WriteLine以写入我启动应用程序的控制台?这对我不起作用 如果相关的话,我使用的是Windows7x64,并且启用了UAC。提升似乎并不能解决问题,使用start/wait也不能解决问题 更新 一些可能有帮助的其他背景: 我刚刚发现,如果我在命令提示符下键入cmd/cmyprogram.exe,那么控制台输出工作正常。如果启动命令提示符,打开cmd.exe子进程,并从该子sh
Windows应用程序
,并使用AttachConsole(-1)
API,如何获取Console.WriteLine
以写入我启动应用程序的控制台?这对我不起作用
如果相关的话,我使用的是Windows7x64,并且启用了UAC。提升似乎并不能解决问题,使用start/wait
也不能解决问题
更新
一些可能有帮助的其他背景:
我刚刚发现,如果我在命令提示符下键入cmd/cmyprogram.exe
,那么控制台输出工作正常。如果启动命令提示符,打开cmd.exe
子进程,并从该子shell运行程序,情况也是如此
我还尝试了注销和重新登录,从“开始”菜单启动的cmd.exe运行(与右键单击->命令提示符相反),然后从运行。这些都不管用
背景
我在其他网站上读过,也读过一些SO的答案,我可以调用win32 APIAttachConsole
,将我的Windows应用程序绑定到运行我的程序的控制台,这样我就可以拥有“既是控制台应用程序,又是Windows应用程序”的东西
例如,这个问题:
我已经编写了一系列逻辑来实现这一点(使用了其他几个API),并且我已经实现了所有其他场景(包括重定向,其他人声称重定向不起作用)。剩下的唯一一个场景是使用Console.WriteLine
写入我启动程序时使用的控制台。从我所读到的一切来看,如果我使用AttachConsole
,这应该是可行的
Repro
这里是一个最小的示例-请注意,该项目被设置为一个Windows应用程序
:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;
class Program
{
[STAThread]
static void Main(string[] args)
{
if (!AttachConsole(-1))
{
MessageBox.Show(
new Win32Exception(Marshal.GetLastWin32Error())
.ToString()
);
}
Console.WriteLine("Test");
}
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern bool AttachConsole(int processId);
}
- 当我在命令提示符下运行它时,我没有得到错误,但也没有得到任何控制台输出。这就是问题所在
- 如果我在应用程序的执行流中的任何位置添加额外的消息框,则会显示消息框。我期待这一切,所以这里一切都很好
- 当我从VisualStudio运行这个程序或双击它时,会显示一个带有错误的消息框。我希望如此,所以这里不用担心(将在我的真实应用程序中使用
)alloconsole
如果在调用
Console.WriteLine
后调用封送处理.GetLastWin32Error
,则会得到错误“System.ComponentModel.Win32Exception(0x80004005):句柄无效”。我怀疑连接到控制台会导致console.Out
出错,但我不确定如何修复它。我在Winforms中就是这样做的。使用WPF也会类似
static class SybilProgram
{
[STAThread]
static void Main(string[] args)
{
if (args.Length > 0)
{
// Command line given, display console
if ( !AttachConsole(ATTACH_PARENT_PROCESS) ) // Attach to a parent process console (-1)
AllocConsole(); // Alloc a new console if none available
ConsoleMain(args);
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1()); // instantiate the Form
}
}
private static void ConsoleMain(string[] args)
{
Console.WriteLine("Command line = {0}", Environment.CommandLine);
for (int ix = 0; ix < args.Length; ++ix)
Console.WriteLine("Argument{0} = {1}", ix + 1, args[ix]);
Console.ReadLine();
}
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AllocConsole();
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AttachConsole(int pid);
}
静态类程序
{
[状态线程]
静态void Main(字符串[]参数)
{
如果(args.Length>0)
{
//给定命令行,显示控制台
如果(!AttachConsole(ATTACH_PARENT_PROCESS))//附加到父进程控制台(-1)
AllocConsole();//如果没有可用的控制台,则分配一个新的控制台
ConsoleMain(args);
}
其他的
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());//实例化表单
}
}
私有静态void控制台main(字符串[]args)
{
WriteLine(“命令行={0}”,Environment.CommandLine);
对于(int-ix=0;ix
我看不出我们的实现之间有任何显著差异。对于它的价值,下面是我在我的应用程序,它的工作很好。我还创建了一个示例WPF应用程序,它也运行良好
我怀疑你的问题在别处。对不起,我帮不上忙了
[STAThread]
public static void Main()
{
AttachProcessToConsole();
}
private static void AttachProcessToConsole()
{
AttachConsole(-1);
}
// Attaches the calling process to the console of the specified process.
// http://msdn.microsoft.com/en-us/library/ms681952%28v=vs.85%29.aspx
[DllImport("Kernel32.dll")]
private static extern bool AttachConsole(int processId);
我遇到了类似的情况:无法让Windows应用程序在以编程方式连接的控制台中输出任何内容。最终,我发现我在AttachConsole之前使用过一次Console.WriteLine,这就破坏了之后的一切。+1 我也有同样的问题。控制台输出不会使用各种风格的
alloconsole
或AttachConsole
显示
检查是否已在项目配置中禁用并启用visual studio宿主进程。启用此选项会神奇地使所有控制台消息按预期显示。我正在运行VS2010和.NET4,但表明该“功能”在VS2012中仍然存在。也有同样的问题,并且在管理员模式下运行
cmd.exe
时,调用成功,但Console.Write()
和Console.WriteLine()
不起作用。如果您正常运行cmd.exe
(非管理员),一切似乎都正常工作。我的应用程序当前版本(目标为.NET 4.0)也遇到了同样的问题,但我确信AttachConsole(-1)
在早期版本(目标为.NET 2.0)中工作正常
我发现只要从应用程序的.exe.config文件中删除(自定义)TraceListener,就可以获得控制台输出,尽管我还不知道为什么
也许这也是吞噬您的控制台输出的原因
更新
事实上,我的自定义跟踪侦听器的目录中有一个Console.WriteLine()
,它把事情搞砸了。删除此行后,附加控制台(-1)后的控制台输出恢复正常。是问题所在
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool AttachConsole(int processId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern IntPtr GetStdHandle(int nStdHandle);
public static void InitConsole()
{
const int STD_OUTPUT_HANDLE = -11;
AttachConsole(-1);
var stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
var safeFileHandle = new SafeFileHandle(stdHandle, true);
var fileStream = new FileStream(safeFileHandle, FileAccess.Write);
var standardOutput = new StreamWriter(fileStream) { AutoFlush = true };
Console.SetOut(standardOutput);
Console.WriteLine();
Console.WriteLine("As seen on StackOverflow!");
}