Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net AttachConsole(-1),但Console.WriteLine赢了';输出到父命令提示符?_.net_Winapi_Pinvoke_Console Application - Fatal编程技术网

.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 API
AttachConsole
,将我的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!");
    }