如何在表单应用程序中显示控制台输出/窗口?

发布于 2024-10-06 08:01:04 字数 565 浏览 0 评论 0原文

为了立即陷入困境,一个非常基本的示例:

using System;
using System.Windows.Forms;

class test
{ 
    static void Main()
    { 
        Console.WriteLine("test");
        MessageBox.Show("test");
    }
}

如果我使用默认选项(在命令行中使用 csc)编译它,如预期的那样,它将编译为控制台应用程序。另外,因为我导入了 System.Windows.Forms,所以它还会显示一个消息框。

现在,如果我使用选项 /target:winexe(我认为该选项与从项目选项中选择 Windows Application 相同),正如预期的那样,我只会看到消息框并且没有控制台输出。

(事实上​​,当它从命令行启动时,我可以在应用程序完成之前发出下一个命令)。

所以,我的问题是 - 我知道您可以从控制台应用程序输出“windows”/表单,但是有没有办法从 Windows 应用程序显示控制台?

To get stuck in straight away, a very basic example:

using System;
using System.Windows.Forms;

class test
{ 
    static void Main()
    { 
        Console.WriteLine("test");
        MessageBox.Show("test");
    }
}

If I compile this with default options (using csc at command line), as expected, it will compile to a console application. Also, because I imported System.Windows.Forms, it will also show a message box.

Now, if I use the option /target:winexe, which I think is the same as choosing Windows Application from within project options, as expected I will only see the Message Box and no console output.

(In fact, the moment it is launched from command line, I can issue the next command before the application has even completed).

So, my question is - I know that you can have "windows"/forms output from a console application, but is there anyway to show the console from a Windows application?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

只等公子 2024-10-13 08:01:04

这个应该可以。

using System.Runtime.InteropServices;

private void Form1_Load(object sender, EventArgs e)
{
    AllocConsole();
}

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AllocConsole();

this one should work.

using System.Runtime.InteropServices;

private void Form1_Load(object sender, EventArgs e)
{
    AllocConsole();
}

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AllocConsole();
且行且努力 2024-10-13 08:01:04

也许这过于简单化了...

创建一个 Windows 窗体项目...

然后:项目属性 ->应用->输出类型->控制台应用程序

然后可以让控制台和表单一起运行,对我有用

Perhaps this is over-simplistic...

Create a Windows Form project...

Then: Project Properties -> Application -> Output Type -> Console Application

Then can have Console and Forms running together, works for me

阳光下慵懒的猫 2024-10-13 08:01:04

如果您不担心按命令打开控制台,则可以进入项目的属性并将其更改为控制台应用程序

更改项目类型的屏幕截图

这仍然会显示您的表单并弹出一个控制台窗口。您无法关闭控制台窗口,但它可以作为一个出色的调试临时记录器。

请记住在部署程序之前将其关闭。

If you are not worrying about opening a console on-command, you can go into the properties for your project and change it to Console Application

screenshot of changing the project type.

This will still show your form as well as popping up a console window. You can't close the console window, but it works as an excellent temporary logger for debugging.

Just remember to turn it back off before you deploy the program.

吾性傲以野 2024-10-13 08:01:04

您可以使用 pinvoke 调用 AttachConsole 来获取附加到 WinForms 项目的控制台窗口:http://www.csharp411.com/console-output-from-winforms-application/

您可能还需要考虑 Log4net ( http://logging.apache.org/log4net/index.html )用于配置不同配置中的日志输出。

You can call AttachConsole using pinvoke to get a console window attached to a WinForms project: http://www.csharp411.com/console-output-from-winforms-application/

You may also want to consider Log4net ( http://logging.apache.org/log4net/index.html ) for configuring log output in different configurations.

ぺ禁宫浮华殁 2024-10-13 08:01:04

创建 Windows 窗体应用程序,并将输出类型更改为控制台。

它将导致控制台和表单打开。

输入图像描述这里

Create a Windows Forms Application, and change the output type to Console.

It will result in both a console and the form to open.

enter image description here

妄司 2024-10-13 08:01:04

这里基本上可能发生两件事。

控制台输出
winforms 程序可以将自身附加到创建它的控制台窗口(或者附加到不同的控制台窗口,或者如果需要的话实际上附加到新的控制台窗口)。一旦连接到控制台窗口 Console.WriteLine() 等就会按预期工作。这种方法的一个问题是程序立即将控制权返回到控制台窗口,然后继续写入,因此用户也可以在控制台窗口中键入内容。我认为您可以使用带有 /wait 参数的 start 来处理这个问题。

启动命令语法的链接

重定向控制台输出
这是当有人将程序的输出传送到其他地方时,例如。

你的应用程序> file.txt

在这种情况下附加到控制台窗口实际上会忽略管道。为了完成这项工作,您可以调用 Console.OpenStandardOutput() 来获取输出应通过管道传输到的流的句柄。这仅在输出通过管道传输时才有效,因此如果您想处理这两种情况,您需要打开标准输出并写入它并附加到控制台窗口。这确实意味着输出被发送到控制台窗口和管道,但这是我能找到的最佳解决方案。下面是我用来执行此操作的代码。

// This always writes to the parent console window and also to a redirected stdout if there is one.
// It would be better to do the relevant thing (eg write to the redirected file if there is one, otherwise
// write to the console) but it doesn't seem possible.
public class GUIConsoleWriter : IConsoleWriter
{
    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    private static extern bool AttachConsole(int dwProcessId);

    private const int ATTACH_PARENT_PROCESS = -1;

    StreamWriter _stdOutWriter;

    // this must be called early in the program
    public GUIConsoleWriter()
    {
        // this needs to happen before attachconsole.
        // If the output is not redirected we still get a valid stream but it doesn't appear to write anywhere
        // I guess it probably does write somewhere, but nowhere I can find out about
        var stdout = Console.OpenStandardOutput();
        _stdOutWriter = new StreamWriter(stdout);
        _stdOutWriter.AutoFlush = true;

        AttachConsole(ATTACH_PARENT_PROCESS);
    }

    public void WriteLine(string line)
    {
        _stdOutWriter.WriteLine(line);
        Console.WriteLine(line);
    }
}

There are basically two things that can happen here.

Console output
It is possible for a winforms program to attach itself to the console window that created it (or to a different console window, or indeed to a new console window if desired). Once attached to the console window Console.WriteLine() etc works as expected. One gotcha to this approach is that the program returns control to the console window immediately, and then carries on writing to it, so the user can also type away in the console window. You can use start with the /wait parameter to handle this I think.

Link to start Command syntax

Redirected console output
This is when someone pipes the output from your program somewhere else, eg.

yourapp > file.txt

Attaching to a console window in this case effectively ignores the piping. To make this work you can call Console.OpenStandardOutput() to get a handle to the stream that the output should be piped to. This only works if the output is piped, so if you want to handle both of the scenarios you need to open the standard output and write to it and attach to the console window. This does mean that the output is sent to the console window and to the pipe but its the best solution I could find. Below the code I use to do this.

// This always writes to the parent console window and also to a redirected stdout if there is one.
// It would be better to do the relevant thing (eg write to the redirected file if there is one, otherwise
// write to the console) but it doesn't seem possible.
public class GUIConsoleWriter : IConsoleWriter
{
    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    private static extern bool AttachConsole(int dwProcessId);

    private const int ATTACH_PARENT_PROCESS = -1;

    StreamWriter _stdOutWriter;

    // this must be called early in the program
    public GUIConsoleWriter()
    {
        // this needs to happen before attachconsole.
        // If the output is not redirected we still get a valid stream but it doesn't appear to write anywhere
        // I guess it probably does write somewhere, but nowhere I can find out about
        var stdout = Console.OpenStandardOutput();
        _stdOutWriter = new StreamWriter(stdout);
        _stdOutWriter.AutoFlush = true;

        AttachConsole(ATTACH_PARENT_PROCESS);
    }

    public void WriteLine(string line)
    {
        _stdOutWriter.WriteLine(line);
        Console.WriteLine(line);
    }
}
山人契 2024-10-13 08:01:04

这对我有用,将输出通过管道传输到文件。
使用以下命令调用控制台

cmd /c“C:\path\to\your\application.exe”> myfile.txt

将此代码添加到您的应用程序中。

    [DllImport("kernel32.dll")]
    static extern bool AttachConsole(UInt32 dwProcessId);
    [DllImport("kernel32.dll")]
    private static extern bool GetFileInformationByHandle(
        SafeFileHandle hFile,
        out BY_HANDLE_FILE_INFORMATION lpFileInformation
        );
    [DllImport("kernel32.dll")]
    private static extern SafeFileHandle GetStdHandle(UInt32 nStdHandle);
    [DllImport("kernel32.dll")]
    private static extern bool SetStdHandle(UInt32 nStdHandle, SafeFileHandle hHandle);
    [DllImport("kernel32.dll")]
    private static extern bool DuplicateHandle(
        IntPtr hSourceProcessHandle,
        SafeFileHandle hSourceHandle,
        IntPtr hTargetProcessHandle,
        out SafeFileHandle lpTargetHandle,
        UInt32 dwDesiredAccess,
        Boolean bInheritHandle,
        UInt32 dwOptions
        );
    private const UInt32 ATTACH_PARENT_PROCESS = 0xFFFFFFFF;
    private const UInt32 STD_OUTPUT_HANDLE = 0xFFFFFFF5;
    private const UInt32 STD_ERROR_HANDLE = 0xFFFFFFF4;
    private const UInt32 DUPLICATE_SAME_ACCESS = 2;
    struct BY_HANDLE_FILE_INFORMATION
    {
        public UInt32 FileAttributes;
        public System.Runtime.InteropServices.ComTypes.FILETIME CreationTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME LastWriteTime;
        public UInt32 VolumeSerialNumber;
        public UInt32 FileSizeHigh;
        public UInt32 FileSizeLow;
        public UInt32 NumberOfLinks;
        public UInt32 FileIndexHigh;
        public UInt32 FileIndexLow;
    }
    static void InitConsoleHandles()
    {
        SafeFileHandle hStdOut, hStdErr, hStdOutDup, hStdErrDup;
        BY_HANDLE_FILE_INFORMATION bhfi;
        hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
        hStdErr = GetStdHandle(STD_ERROR_HANDLE);
        // Get current process handle
        IntPtr hProcess = Process.GetCurrentProcess().Handle;
        // Duplicate Stdout handle to save initial value
        DuplicateHandle(hProcess, hStdOut, hProcess, out hStdOutDup,
        0, true, DUPLICATE_SAME_ACCESS);
        // Duplicate Stderr handle to save initial value
        DuplicateHandle(hProcess, hStdErr, hProcess, out hStdErrDup,
        0, true, DUPLICATE_SAME_ACCESS);
        // Attach to console window – this may modify the standard handles
        AttachConsole(ATTACH_PARENT_PROCESS);
        // Adjust the standard handles
        if (GetFileInformationByHandle(GetStdHandle(STD_OUTPUT_HANDLE), out bhfi))
        {
            SetStdHandle(STD_OUTPUT_HANDLE, hStdOutDup);
        }
        else
        {
            SetStdHandle(STD_OUTPUT_HANDLE, hStdOut);
        }
        if (GetFileInformationByHandle(GetStdHandle(STD_ERROR_HANDLE), out bhfi))
        {
            SetStdHandle(STD_ERROR_HANDLE, hStdErrDup);
        }
        else
        {
            SetStdHandle(STD_ERROR_HANDLE, hStdErr);
        }
    }

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        // initialize console handles
        InitConsoleHandles();

        if (args.Length != 0)
        {

            if (args[0].Equals("waitfordebugger"))
            {
                MessageBox.Show("Attach the debugger now");
            }
            if (args[0].Equals("version"))
            {
#if DEBUG
                String typeOfBuild = "d";
#else
                String typeOfBuild = "r";
#endif
                String output = typeOfBuild + Assembly.GetExecutingAssembly()
                    .GetName().Version.ToString();
                //Just for the fun of it
                Console.Write(output);
                Console.Beep(4000, 100);
                Console.Beep(2000, 100);
                Console.Beep(1000, 100);
                Console.Beep(8000, 100);
                return;
            }
        }
    }

我在这里找到了这段代码: http://www.csharp411.com/console -输出来自-winforms-application/
我认为也值得将其发布在这里。

This worked for me, to pipe the output to a file.
Call the console with

cmd /c "C:\path\to\your\application.exe" > myfile.txt

Add this code to your application.

    [DllImport("kernel32.dll")]
    static extern bool AttachConsole(UInt32 dwProcessId);
    [DllImport("kernel32.dll")]
    private static extern bool GetFileInformationByHandle(
        SafeFileHandle hFile,
        out BY_HANDLE_FILE_INFORMATION lpFileInformation
        );
    [DllImport("kernel32.dll")]
    private static extern SafeFileHandle GetStdHandle(UInt32 nStdHandle);
    [DllImport("kernel32.dll")]
    private static extern bool SetStdHandle(UInt32 nStdHandle, SafeFileHandle hHandle);
    [DllImport("kernel32.dll")]
    private static extern bool DuplicateHandle(
        IntPtr hSourceProcessHandle,
        SafeFileHandle hSourceHandle,
        IntPtr hTargetProcessHandle,
        out SafeFileHandle lpTargetHandle,
        UInt32 dwDesiredAccess,
        Boolean bInheritHandle,
        UInt32 dwOptions
        );
    private const UInt32 ATTACH_PARENT_PROCESS = 0xFFFFFFFF;
    private const UInt32 STD_OUTPUT_HANDLE = 0xFFFFFFF5;
    private const UInt32 STD_ERROR_HANDLE = 0xFFFFFFF4;
    private const UInt32 DUPLICATE_SAME_ACCESS = 2;
    struct BY_HANDLE_FILE_INFORMATION
    {
        public UInt32 FileAttributes;
        public System.Runtime.InteropServices.ComTypes.FILETIME CreationTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME LastWriteTime;
        public UInt32 VolumeSerialNumber;
        public UInt32 FileSizeHigh;
        public UInt32 FileSizeLow;
        public UInt32 NumberOfLinks;
        public UInt32 FileIndexHigh;
        public UInt32 FileIndexLow;
    }
    static void InitConsoleHandles()
    {
        SafeFileHandle hStdOut, hStdErr, hStdOutDup, hStdErrDup;
        BY_HANDLE_FILE_INFORMATION bhfi;
        hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
        hStdErr = GetStdHandle(STD_ERROR_HANDLE);
        // Get current process handle
        IntPtr hProcess = Process.GetCurrentProcess().Handle;
        // Duplicate Stdout handle to save initial value
        DuplicateHandle(hProcess, hStdOut, hProcess, out hStdOutDup,
        0, true, DUPLICATE_SAME_ACCESS);
        // Duplicate Stderr handle to save initial value
        DuplicateHandle(hProcess, hStdErr, hProcess, out hStdErrDup,
        0, true, DUPLICATE_SAME_ACCESS);
        // Attach to console window – this may modify the standard handles
        AttachConsole(ATTACH_PARENT_PROCESS);
        // Adjust the standard handles
        if (GetFileInformationByHandle(GetStdHandle(STD_OUTPUT_HANDLE), out bhfi))
        {
            SetStdHandle(STD_OUTPUT_HANDLE, hStdOutDup);
        }
        else
        {
            SetStdHandle(STD_OUTPUT_HANDLE, hStdOut);
        }
        if (GetFileInformationByHandle(GetStdHandle(STD_ERROR_HANDLE), out bhfi))
        {
            SetStdHandle(STD_ERROR_HANDLE, hStdErrDup);
        }
        else
        {
            SetStdHandle(STD_ERROR_HANDLE, hStdErr);
        }
    }

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        // initialize console handles
        InitConsoleHandles();

        if (args.Length != 0)
        {

            if (args[0].Equals("waitfordebugger"))
            {
                MessageBox.Show("Attach the debugger now");
            }
            if (args[0].Equals("version"))
            {
#if DEBUG
                String typeOfBuild = "d";
#else
                String typeOfBuild = "r";
#endif
                String output = typeOfBuild + Assembly.GetExecutingAssembly()
                    .GetName().Version.ToString();
                //Just for the fun of it
                Console.Write(output);
                Console.Beep(4000, 100);
                Console.Beep(2000, 100);
                Console.Beep(1000, 100);
                Console.Beep(8000, 100);
                return;
            }
        }
    }

I found this code here: http://www.csharp411.com/console-output-from-winforms-application/
I thought is was worthy to post it here as well.

情绪 2024-10-13 08:01:04
//From your application set the Console to write to your RichTextkBox 
//object:
Console.SetOut(new RichTextBoxWriter(yourRichTextBox));

//To ensure that your RichTextBox object is scrolled down when its text is 
//changed add this event:
private void yourRichTextBox_TextChanged(object sender, EventArgs e)
{
    yourRichTextBox.SelectionStart = yourRichTextBox.Text.Length;
    yourRichTextBox.ScrollToCaret();
}

public delegate void StringArgReturningVoidDelegate(string text);
public class RichTextBoxWriter : TextWriter
{
    private readonly RichTextBox _richTextBox;
    public RichTextBoxWriter(RichTextBox richTexttbox)
    {
        _richTextBox = richTexttbox;
    }

    public override void Write(char value)
    {
        SetText(value.ToString());
    }

    public override void Write(string value)
    {
        SetText(value);
    }

    public override void WriteLine(char value)
    {
        SetText(value + Environment.NewLine);
    }

    public override void WriteLine(string value)
    {
        SetText(value + Environment.NewLine);
    }

    public override Encoding Encoding => Encoding.ASCII;

    //Write to your UI object in thread safe way:
    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the  
        // calling thread to the thread ID of the creating thread.  
        // If these threads are different, it returns true.  
        if (_richTextBox.InvokeRequired)
        {
            var d = new StringArgReturningVoidDelegate(SetText);
            _richTextBox.Invoke(d, text);
        }
        else
        {
            _richTextBox.Text += text;
        }
    }
}
//From your application set the Console to write to your RichTextkBox 
//object:
Console.SetOut(new RichTextBoxWriter(yourRichTextBox));

//To ensure that your RichTextBox object is scrolled down when its text is 
//changed add this event:
private void yourRichTextBox_TextChanged(object sender, EventArgs e)
{
    yourRichTextBox.SelectionStart = yourRichTextBox.Text.Length;
    yourRichTextBox.ScrollToCaret();
}

public delegate void StringArgReturningVoidDelegate(string text);
public class RichTextBoxWriter : TextWriter
{
    private readonly RichTextBox _richTextBox;
    public RichTextBoxWriter(RichTextBox richTexttbox)
    {
        _richTextBox = richTexttbox;
    }

    public override void Write(char value)
    {
        SetText(value.ToString());
    }

    public override void Write(string value)
    {
        SetText(value);
    }

    public override void WriteLine(char value)
    {
        SetText(value + Environment.NewLine);
    }

    public override void WriteLine(string value)
    {
        SetText(value + Environment.NewLine);
    }

    public override Encoding Encoding => Encoding.ASCII;

    //Write to your UI object in thread safe way:
    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the  
        // calling thread to the thread ID of the creating thread.  
        // If these threads are different, it returns true.  
        if (_richTextBox.InvokeRequired)
        {
            var d = new StringArgReturningVoidDelegate(SetText);
            _richTextBox.Invoke(d, text);
        }
        else
        {
            _richTextBox.Text += text;
        }
    }
}
无力看清 2024-10-13 08:01:04

基于 Chaz 的答案,在 .NET 5 中,有 重大更改,因此需要在项目文件中进行两处修改,即更改 OutputType 和添加 DisableWinExeOutputInference。例子:

<PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0-windows10.0.17763.0</TargetFramework>
    <UseWindowsForms>true</UseWindowsForms>
    <DisableWinExeOutputInference>true</DisableWinExeOutputInference>
    <Platforms>AnyCPU;x64;x86</Platforms>
</PropertyGroup>

Building on Chaz's answer, in .NET 5 there is a breaking change, so two modifications are required in the project file, i.e. changing OutputType and adding DisableWinExeOutputInference. Example:

<PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0-windows10.0.17763.0</TargetFramework>
    <UseWindowsForms>true</UseWindowsForms>
    <DisableWinExeOutputInference>true</DisableWinExeOutputInference>
    <Platforms>AnyCPU;x64;x86</Platforms>
</PropertyGroup>
ま柒月 2024-10-13 08:01:04
using System;
using System.Runtime.InteropServices;

namespace SomeProject
{
    class GuiRedirect
    {
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool AttachConsole(int dwProcessId);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr GetStdHandle(StandardHandle nStdHandle);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool SetStdHandle(StandardHandle nStdHandle, IntPtr handle);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern FileType GetFileType(IntPtr handle);

    private enum StandardHandle : uint
    {
        Input = unchecked((uint)-10),
        Output = unchecked((uint)-11),
        Error = unchecked((uint)-12)
    }

    private enum FileType : uint
    {
        Unknown = 0x0000,
        Disk = 0x0001,
        Char = 0x0002,
        Pipe = 0x0003
    }

    private static bool IsRedirected(IntPtr handle)
    {
        FileType fileType = GetFileType(handle);

        return (fileType == FileType.Disk) || (fileType == FileType.Pipe);
    }

    public static void Redirect()
    {
        if (IsRedirected(GetStdHandle(StandardHandle.Output)))
        {
            var initialiseOut = Console.Out;
        }

        bool errorRedirected = IsRedirected(GetStdHandle(StandardHandle.Error));
        if (errorRedirected)
        {
            var initialiseError = Console.Error;
        }

        AttachConsole(-1);

        if (!errorRedirected)
            SetStdHandle(StandardHandle.Error, GetStdHandle(StandardHandle.Output));
    }
}
using System;
using System.Runtime.InteropServices;

namespace SomeProject
{
    class GuiRedirect
    {
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool AttachConsole(int dwProcessId);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr GetStdHandle(StandardHandle nStdHandle);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool SetStdHandle(StandardHandle nStdHandle, IntPtr handle);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern FileType GetFileType(IntPtr handle);

    private enum StandardHandle : uint
    {
        Input = unchecked((uint)-10),
        Output = unchecked((uint)-11),
        Error = unchecked((uint)-12)
    }

    private enum FileType : uint
    {
        Unknown = 0x0000,
        Disk = 0x0001,
        Char = 0x0002,
        Pipe = 0x0003
    }

    private static bool IsRedirected(IntPtr handle)
    {
        FileType fileType = GetFileType(handle);

        return (fileType == FileType.Disk) || (fileType == FileType.Pipe);
    }

    public static void Redirect()
    {
        if (IsRedirected(GetStdHandle(StandardHandle.Output)))
        {
            var initialiseOut = Console.Out;
        }

        bool errorRedirected = IsRedirected(GetStdHandle(StandardHandle.Error));
        if (errorRedirected)
        {
            var initialiseError = Console.Error;
        }

        AttachConsole(-1);

        if (!errorRedirected)
            SetStdHandle(StandardHandle.Error, GetStdHandle(StandardHandle.Output));
    }
}
风铃鹿 2024-10-13 08:01:04

在项目属性中将输出类型设置为控制台将为您提供一个控制台应用程序以及您创建的表单。

Setting the output type as Console in the project properties will give you a Console application along with the form you created.

维持三分热 2024-10-13 08:01:04

如果您想要的是简单的调试输出,以下内容对我有用。我正在使用 C# 中的 VS 2022 编程

添加“使用 System.Diagnostics”

,然后

  Debug.WriteLine("*****");
  Debug.WriteLine(...);
  Debug.WriteLine("");

输出出现在 VS2022 的调试控制台中。那里有很多东西,所以我使用 Debug.WriteLine("*****") 和 Debug.WriteLine("") 来帮助我找到我的输出。您还可以在启动后清除调试输出。

我仍在工作,但在 VS 下运行,运行调试时没有输出

if what you want is simple debug output the following works for me. I am using VS 2022 programming in C#

add "using System.Diagnostics"

then

  Debug.WriteLine("*****");
  Debug.WriteLine(...);
  Debug.WriteLine("");

THe output appears in the debug console of VS2022. There is a lot of stuff there so I use the Debug.WriteLine("*****") and Debug.WriteLine("") to help me find my output. You can also clear the debug output after start up.

I am still working but running under VS there is no output when running wo debugging

謸气贵蔟 2024-10-13 08:01:04

要在 WinForm 应用程序中同时拥有窗口和控制台,一个可行的解决方案(以 .Net6.0 和 Windows 作为目标操作系统)如下:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public partial class MyMainForm : Form
{
    [DllImport("kernel32.dll")]
    private static extern bool AllocConsole();
    [DllImport("kernel32.dll")]
    private static extern bool FreeConsole();

    private int interval = default;
    
    public MyMainForm()
    {
        InitializeComponent(); // default winform designer initialize method
        Invalidate();
        AllocConsole();

        // You can write text to the console within the constructor.
        System.Console.WriteLine("*** Closing the console will close application as well ***");
        this.FormClosing += (s, e) => FreeConsole();
        this.KeyDown += (s, e) => System.Console.WriteLine(interval++);
    }
}

To have both window and console in WinForm application, a working solution (with .Net6.0 and Windows as the targeted OS) is as follows:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public partial class MyMainForm : Form
{
    [DllImport("kernel32.dll")]
    private static extern bool AllocConsole();
    [DllImport("kernel32.dll")]
    private static extern bool FreeConsole();

    private int interval = default;
    
    public MyMainForm()
    {
        InitializeComponent(); // default winform designer initialize method
        Invalidate();
        AllocConsole();

        // You can write text to the console within the constructor.
        System.Console.WriteLine("*** Closing the console will close application as well ***");
        this.FormClosing += (s, e) => FreeConsole();
        this.KeyDown += (s, e) => System.Console.WriteLine(interval++);
    }
}
左秋 2024-10-13 08:01:04

为什么不将其保留为窗口窗体应用程序,并创建一个简单的窗体来模仿控制台。该窗体可以看起来就像黑屏控制台一样,并让它直接响应按键。
然后,在program.cs 文件中,您决定是否需要运行主窗体或ConsoleForm。例如,我使用这种方法来捕获program.cs 文件中的命令行参数。我创建 ConsoleForm,最初隐藏它,然后将命令行字符串传递给其中的 AddCommand 函数,该函数显示允许的命令。最后,如果用户给出 -h 或 -?命令,我在 ConsoleForm 上调用 .Show,当用户按下其上的任意键时,我关闭程序。如果用户不给出 -?命令,我关闭隐藏的 ConsoleForm 并运行主窗体。

Why not just leave it as a Window Forms app, and create a simple form to mimic the Console. The form can be made to look just like the black-screened Console, and have it respond directly to key press.
Then, in the program.cs file, you decide whether you need to Run the main form or the ConsoleForm. For example, I use this approach to capture the command line arguments in the program.cs file. I create the ConsoleForm, initially hide it, then pass the command line strings to an AddCommand function in it, which displays the allowed commands. Finally, if the user gave the -h or -? command, I call the .Show on the ConsoleForm and when the user hits any key on it, I shut down the program. If the user doesn't give the -? command, I close the hidden ConsoleForm and Run the main form.

对你而言 2024-10-13 08:01:04

您可以随时在应用程序类型、控制台或窗口之间切换。因此,您不会编写特殊的逻辑来查看标准输出。此外,当在调试器中运行应用程序时,您将在输出窗口中看到所有标准输出。您也可以只添加一个断点,并在断点属性中更改“When Hit...”,您可以输出任何消息和变量。您还可以选中/取消选中“继续执行”,您的断点将变成方形。因此,断点消息不会在调试输出窗口中更改应用程序中的任何内容。

You can any time switch between type of applications, to console or windows. So, you will not write special logic to see the stdout. Also, when running application in debugger, you will see all the stdout in output window. You might also just add a breakpoint, and in breakpoint properties change "When Hit...", you can output any messages, and variables. Also you can check/uncheck "Continue execution", and your breakpoint will become square shaped. So, the breakpoint messages without changhing anything in the application in the debug output window.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文