[英]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.