C# WinForm程序向控制台输出信息

Windows窗口程序向控制台输出信息的两种方案

场景一:

用户双击exe时,除了打开程序窗口外,你还希望打开一个控制台窗口,用于输出调试信息。

这种场景下,你需要创建一个Console窗口,并把std::cout输出流定位到这个窗口上,如下代码所示:

#include <iostream>
#include <fcntl.h>
#include <Windows.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
 
if (!::AttachConsole(ATTACH_PARENT_PROCESS)) {
  if (::AllocConsole()) {
    FILE* unused;
    if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
        _dup2(_fileno(stdout), 1);
    }
    if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
        _dup2(_fileno(stdout), 2);
    }
    std::ios::sync_with_stdio();
  }
}

AllocConsole方法负责创建一个Console窗口。

场景二:

当用户在控制台窗口,通过命令行启动你的应用程序时,你希望向用户打开的控制台窗口输出信息。

这种场景下,你只要附加当前控制台窗口即可,如下代码所示:

#include <iostream>
#include <fcntl.h>
#include <Windows.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
 
if (::AttachConsole(ATTACH_PARENT_PROCESS)) {
    FILE* unused;
    if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
        _dup2(_fileno(stdout), 1);
    }
    if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
        _dup2(_fileno(stdout), 2);
    }
    std::ios::sync_with_stdio();
}

AttachConsole方法负责附加当前控制台窗口。

程序运行效果如下图所示:

 

出处:https://zhuanlan.zhihu.com/p/28054430402

=======================================================================================

    控制台作为信息显示窗口对于调试程序查找程序BUG有诸多好处,所以给GUI程序绑定一个控制台窗口用于显示程序运行时的状态是非常有必要的,否则就需要用WinForm的控件自己去实现了。首先想让WinForm程序绑定控制台窗口需要调用Windows API,需要先导入命名空间:

using System.Runtime.InteropServices;

然后导入dll:

[DllImport("kernel32.dll")]
public static extern bool AllocConsole();
 
[DllImport("kernel32.dll")]
public static extern bool FreeConsole();

然后在构造函数中关联一个控制台:

AllocConsole(); //关联一个控制台窗口用于显示信息

释放关联的控制台:

FreeConsole();//释放关联的控制台,不然会报错

在设计窗口上点击窗口,不要点击窗口上的控件,设置窗口关闭前的回调函数:

 

再弄一个按钮控件用于测试向控制台输出字符串:

System.Console.WriteLine("春哥纯爷们!");

 

下面是完整的示例:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;

//此文件存放的是窗口控件的回调函数
namespace Untrie
{
    public partial class Form1 : Form
    {
        [DllImport("kernel32.dll")]
        public static extern bool AllocConsole();//关联一个控制台窗口

        [DllImport("kernel32.dll")]
        public static extern bool FreeConsole();//释放关联的控制台窗口

        public Form1()
        {
            InitializeComponent();
            AllocConsole(); //关联一个控制台窗口用于显示信息
        }

        private void button1_Click(object sender, EventArgs e)
        {
            System.Console.WriteLine("春哥纯爷们!");
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //窗口关闭前 回调函数
            FreeConsole();//释放关联的控制台,不然会报错
        }
    }
}

清除控制台窗口中的内容:

System.Console.Clear();

 

2024-09-03 16:33:33【出处】:https://blog.csdn.net/l198738655/article/details/119572235

参考:https://www.cnblogs.com/NewCivil/archive/2009/04/28/1444745.html

=======================================================================================

命令行启动WinForm程序AttachConsole窗口

<在WinForm应用程序中,如果你想在控制台窗口中运行你的WinForm应用程序并捕获其输出,你可以使用AttachConsole函数。这个函数允许你将一个已经运行的Windows应用程序的控制台输出重定向到一个新的控制台窗口。这对于调试或者需要从应用程序中输出日志信息到控制台窗口非常有用。

如何在WinForm应用程序中使用AttachConsole

确保你的WinForm项目支持控制台输出:

默认情况下,WinForm项目不包含控制台支持。为了使用AttachConsole,你需要在项目中启用控制台。这可以通过在项目的.csproj文件中添加以下属性来实现:

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework> <!-- 或其他支持的.NET版本 -->
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>

在WinForm应用程序的入口点调用AttachConsole

在你的WinForm应用程序的Main方法中,或者在程序启动的早期阶段,调用AttachConsole函数。例如:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
 
static class Program
{
    [DllImport("kernel32.dll")]
    static extern bool AttachConsole(int dwProcessId);
 
    [STAThread]
    static void Main()
    {
        Application.SetHighDpiMode(HighDpiMode.SystemAware);
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        
        // 尝试附加到父进程的控制台(如果有的话)
        if (!AttachConsole(-1))
        {
            // 如果没有父控制台,则创建一个新的控制台窗口
            AllocConsole();
        }
        
        // 现在可以重定向输出到控制台了
        Console.WriteLine("Hello, World!");
        
        Application.Run(new MainForm());
    }
}

使用AllocConsole创建新的控制台窗口

如果你想要确保总是创建一个新的控制台窗口,可以使用AllocConsole函数。这个函数在AttachConsole失败时调用,通常是因为没有父控制台可用。例如:

[DllImport("kernel32.dll")]
static extern bool AllocConsole();

注意事项

  • 使用AttachConsole(-1)尝试附加到调用进程的父控制台。如果没有父控制台(例如,当应用程序从IDE启动或以服务方式运行时),它将失败。在这种情况下,使用AllocConsole()创建一个新的控制台窗口。

  • 确保你的应用程序在调用AttachConsoleAllocConsole之前没有进行任何输出操作,因为一旦这些函数被调用,标准输出流将被重定向到新的控制台。如果在调用这些函数之前有输出操作,可能会导致异常或不可预测的行为。

  • 使用.NET Core或更新的.NET版本时,确保你的项目文件正确配置了输出类型和框架版本。

通过以上步骤,你可以在WinForm应用程序中实现控制台窗口的输出重定向。这对于调试和日志记录非常有用。

提示:AI自动生成,仅供参考

 

出处:百度AI搜索

=======================================================================================

按照上面的用法和说明,我们可以只附加到现有的命令行窗口,如果没有开启命令行窗口,就可以不用输出信息。

同样是在Program.cs文件中,也可以把AttachConsole的结果保存到全局变量中去,方便其他地方使用。

            // 尝试附加到父进程的控制台(如果有的话)
            var b = false;
            b = AttachConsole(-1);
            if (b)
            {
                // 现在可以重定向输出到控制台了
            }

也可以结合AllocConsole和FreeConsole函数同时使用,具体看自己的需求。

=======================================================================================

Windows窗口程序,如何启动一个命令行调试窗口

关于这个问题,如果对Windows API熟悉的话,应该会特别简单,其实就是一个调API的过程,直接分享代码吧。

 

void setupConsole(std::string title)
{
    AllocConsole();
    AttachConsole(GetCurrentProcessId());
    FILE *stream;
    freopen_s(&stream, "CONOUT$", "w+", stdout);
    freopen_s(&stream, "CONOUT$", "w+", stderr);
    SetConsoleTitle(TEXT(title.c_str()));
}

 

出处:https://blog.csdn.net/u013001137/article/details/122483401

=======================================================================================

这种方式多半用在没 VS 的情况,也就是编译后的程序。
如你开发一个winForm 程序想临时打开命令行看一些调试信息; 
我说的是在客户那里,如果在开发机我当然知道可以直接编译成命令行的怎么都可以了(不可能给客户发一个还开个命令行的程序的如果是winForm 的程序) 

 

注意:

此处使用的时候,必须程序开始运行的时候就需要AllocConsole,我自己测试的时候,如在窗体的按钮事件中,在AllocConsole,则无法使用Console.WriteLine命令行显示信息,可能就我一个人是这样的情况吧。

 

使用示例可参考:C#开发一个混合Windows服务和Windows窗体的程序

posted on 2024-09-03 16:34  jack_Meng  阅读(587)  评论(0)    收藏  举报

导航