Wil*_*Wil 114 c# compilation console-application winforms
要立即陷入困境,这是一个非常基本的例子:
using System;
using System.Windows.Forms;
class test
{
static void Main()
{
Console.WriteLine("test");
MessageBox.Show("test");
}
}
Run Code Online (Sandbox Code Playgroud)
如果我使用默认选项(在命令行使用csc)编译它,正如预期的那样,它将编译到控制台应用程序.另外,因为我导入了System.Windows.Forms
,它还会显示一个消息框.
现在,如果我使用该选项/target:winexe
,我认为Windows Application
与在项目选项中选择相同,正如预期的那样,我只会看到消息框而没有控制台输出.
(事实上,从命令行启动它的那一刻,我可以在应用程序完成之前发出下一个命令).
所以,我的问题是 - 我知道你可以从控制台应用程序获得"windows"/表单输出,但是无论如何从Windows应用程序显示控制台?
wiz*_*rdz 137
这一个应该工作.
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();
Run Code Online (Sandbox Code Playgroud)
小智 123
也许这过于简单......
创建Windows窗体项目...
然后:项目属性 - >应用程序 - >输出类型 - >控制台应用程序
然后可以让Console和Forms一起运行,对我有用
gun*_*171 56
如果您不担心打开控制台on-command,可以进入项目的属性并将其更改为Console Application
这仍然会显示您的表单以及弹出控制台窗口.您无法关闭控制台窗口,但它可以作为调试的优秀临时记录器.
只需记住在部署程序之前将其关闭.
Ada*_*erg 16
您可以AttachConsole
使用pinvoke 调用以获得连接到WinForms项目的控制台窗口:http://www.csharp411.com/console-output-from-winforms-application/
您可能还需要考虑使用Log4net(http://logging.apache.org/log4net/index.html)来配置不同配置的日志输出.
Ped*_*ues 13
创建一个 Windows 窗体应用程序,并将输出类型更改为控制台。
这将导致控制台和表单都打开。
ced*_*edd 11
这里基本上可以发生两件事.
控制台输出winforms程序可以将自身附加到创建它的控制台窗口(或者如果需要,可以附加到不同的控制台窗口,或者实际上附加到新的控制台窗口).一旦附加到控制台窗口,Console.WriteLine()等按预期工作.这种方法的一个问题是程序立即将控制权返回到控制台窗口,然后继续写入,因此用户也可以在控制台窗口中输入.你可以使用start和/ wait参数来处理这个问题.
重定向控制台输出当有人将程序的输出从其他地方传输出来时,例如.
yourapp> 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);
}
}
Run Code Online (Sandbox Code Playgroud)
Mik*_*erk 11
这对我有用,可以将输出传递给文件.用控制台调用
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里找到了这个代码:http://www.csharp411.com/console-output-from-winforms-application/ 我认为这也值得在这里发布.
小智 7
根据 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>
Run Code Online (Sandbox Code Playgroud)
//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;
}
}
}
Run Code Online (Sandbox Code Playgroud)