Con*_*ngo 5 .net c# visual-studio
以下程序在"Console.ReadKey()"上引发错误.
禁用后如何重新启用控制台?
using System;
using System.Threading;
using System.Runtime.InteropServices;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem((o) =>
{
Thread.Sleep(1000);
IntPtr stdin = GetStdHandle(StdHandle.Stdin);
CloseHandle(stdin);
});
Console.ReadLine();
Console.Write("ReadLine() successfully aborted by background thread.\n");
Console.Write("[any key to exit]");
Console.ReadKey(); // Throws an exception "Cannot read keys when either application does not have a console or when console input has been redirected from a file. Try Console.Read."
}
// P/Invoke:
private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };
[DllImport("kernel32.dll")]
private static extern IntPtr GetStdHandle(StdHandle std);
[DllImport("kernel32.dll")]
private static extern bool CloseHandle(IntPtr hdl);
}
}
Run Code Online (Sandbox Code Playgroud)
专家额外
如果您想知道,我需要能够在C#中杀死运行ReadLine()的后台线程.这似乎是唯一的方法(thread.Abort将无法工作,因为ReadLine()在操作系统的内部深处运行,在非托管代码中).在StackOverflow上有很多关于这个主题的讨论,没有人真正发现(或发布)一个令人满意的中止Console.ReadLine()的方法.我认为这段代码是正确的 - 如果只有我们可以在禁用它后重新启用它.
使用PostMessage将[enter]发送到当前进程:
class Program
{
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
private static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
const int VK_RETURN = 0x0D;
const int WM_KEYDOWN = 0x100;
static void Main(string[] args)
{
Console.Write("Switch focus to another window now to verify this works in a background process.\n");
ThreadPool.QueueUserWorkItem((o) =>
{
Thread.Sleep(4000);
var hWnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 0);
});
Console.ReadLine();
Console.Write("ReadLine() successfully aborted by background thread.\n");
Console.Write("[any key to exit]");
Console.ReadKey();
}
}
Run Code Online (Sandbox Code Playgroud)
这个答案也解决了这样一个事实,即在ReadLine()上调用.Abort将无法工作,因为代码在Windows内核深处的非托管代码中运行.
这个答案优于任何仅在当前进程具有焦点时才有效的答案,例如SendKeys和Input Simulator.
这个答案优于关闭当前控制台句柄的方法,因为关闭当前控制台句柄的行为导致将来调用ReadLine()抛出错误.
不知道它是否有帮助,但是当我需要能够在 win 表单应用程序中写入控制台时,我使用了此类:
public class ConsoleHelper
{
/// <summary>
/// Allocates a new console for current process.
/// </summary>
[DllImport("kernel32.dll")]
public static extern Boolean AllocConsole();
/// <summary>
/// Frees the console.
/// </summary>
[DllImport("kernel32.dll")]
public static extern Boolean FreeConsole();
}
Run Code Online (Sandbox Code Playgroud)
调用 AllocConsole 创建一个控制台,然后您可以对其进行写入(和读取)。完成后,然后调用 FreeConsole。
| 归档时间: |
|
| 查看次数: |
2414 次 |
| 最近记录: |