[英]Code stops executing when a user clicks on the console window
我有一个控制台应用程序,无需用户交互即可执行我的代码。 如果用户有意或无意地在控制台窗口内单击,则所有执行都将停止。
这与从控制台窗口复制文本有关。 应用程序再次开始执行的唯一方法是,如果用户选择文本,然后右键单击控制台窗口,将其复制到剪贴板。
要查看此操作,请创建一个控制台应用程序并添加以下代码。
class Program
{
static void Main(string[] args)
{
var task = Task.Run(async () =>
{
int i = 0;
while (true)
{
Console.WriteLine(i++);
await Task.Delay(1000);
}
});
Console.ReadLine();
}
}
单击控制台窗口时,任务线程停止执行。 这根本不是理想的行为,我想在我的控制台应用程序中防止这种情况发生。
我怎么能阻止这个? 据我所知,控制台窗口上的所有属性/事件都与控制此行为无关。
如果在控制台窗口中启用了“快速编辑模式”,则会发生这种情 如果右键单击标题栏并选择“属性”,然后选择“选项”选项卡,则可以检查是否启用了“快速编辑模式”。 如果禁用“快速编辑模式”,则单击窗口时滚动不会停止。
滚动停止的原因是因为在窗口中单击鼠标用于选择文本。
您可以在程序中禁用控制台上的“快速编辑模式”,但这样做需要调用GetConsoleMode和SetConsoleMode API函数。 这是你如何做到的:
[DllImport("kernel32.dll", SetLastError=true)]
public static extern IntPtr GetConsoleWindow();
[DllImport("kernel32.dll", SetLastError=true)]
public static extern bool GetConsoleMode(
IntPtr hConsoleHandle,
out int lpMode);
[DllImport("kernel32.dll", SetLastError=true)]
public static extern bool SetConsoleMode(
IntPtr hConsoleHandle,
int ioMode);
/// <summary>
/// This flag enables the user to use the mouse to select and edit text. To enable
/// this option, you must also set the ExtendedFlags flag.
/// </summary>
const int QuickEditMode = 64;
// ExtendedFlags must be combined with
// InsertMode and QuickEditMode when setting
/// <summary>
/// ExtendedFlags must be enabled in order to enable InsertMode or QuickEditMode.
/// </summary>
const int ExtendedFlags = 128;
void DisableQuickEdit()
{
IntPtr conHandle = GetConsoleWindow();
int mode;
if (!GetConsoleMode(conHandle, out mode))
{
// error getting the console mode. Exit.
return;
}
mode = mode & ~(QuickEditMode | ExtendedFlags);
if (!SetConsoleMode(conHandle, mode))
{
// error setting console mode.
}
}
void EnableQuickEdit()
{
IntPtr conHandle = GetConsoleWindow();
int mode;
if (!GetConsoleMode(conHandle, out mode))
{
// error getting the console mode. Exit.
return;
}
mode = mode | (QuickEditMode | ExtendedFlags);
if (!SetConsoleMode(conHandle, mode))
{
// error setting console mode.
}
}
如果沿着这条路走下去,那么在程序启动时保存原始控制台模式设置可能是个好主意,并在程序退出时恢复它。 所以在启动时:
GetConsoleMode(GetConsoleWindow(), ref saveConsoleMode);
当你的程序终止时:
SetConsoleMode(GetConsoleWindow(), saveConsoleMode);
当然,有适当的错误处理。 如果对GetConsoleMode
的调用失败,则不希望恢复控制台模式。
我刚刚看到OP的问题评论中的这个答案包含了我自己发现的内容。 我会保留我的答案,因为人们可能看不到它,就像我一样,它会为他们节省很多时间。
吉姆的回答对我不起作用,我无法弄明白为什么。 我挖掘并找到了一个有效的解决方案,所以我将分享我的发现,希望能帮助处于相同情况的人。
问题是我从GetConsoleWindow()
获得的句柄,它给出了Win32错误(0x6),当我尝试使用它时句柄无效。 对SetConsoleMode()
的调用什么也没做。
为了得到一个工作句柄,我使用GetStdHandle()
来获取控制台的Input句柄。 将此添加到Jim的代码中:
public const int STD_INPUT_HANDLE = -10;
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);
然后更换GetConsoleWindow()
由GetStdHandle(STD_INPUT_HANDLE)
在DisableQuickEdit()
和EnableQuickEdit()
在吉姆的代码。
调用DisableQuickEdit()
,在控制台中禁用选择。
谢谢吉姆!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.