控制台程序线程莫名被阻塞

写了个控制台小程序,起线程通过UDP循环接收数据,在windows server2019执行,

发现运行一会儿就莫名阻塞,端口在正常监听,但是不收任何数据。

通过嗅探工具能发现数据到达端口,最后发现敲下回车就好了,推测是什么挂起了线程。

在windous7开发机上跑测试时,从来没有这种情况。

对比控制台窗口发现,win2019的窗口可以直接拖选操作,打开控制台窗口属性,

发现比win7多了很多选项,最后发现取消控制台窗口的“快速编辑模式”就好了。

win7下也有“快速编辑模式”只是默认不选,而win2019默认是选中的。

对此感觉很无语,从网上搜索相关资料,找到峡州仙士近期发的文章,供参考。

---------------------------下面是转载内容---shellching注--------------------------------------------------------

windows10 cmd命令提示符/批处理/终端 快速编辑模式bug 程序运行被阻塞 顶部标题栏提示选择 需要回车才能继续执行

为什么出现这种情况?

这是快速编辑模式的功能。当程序不断滚动控制台窗口的内容时,用户无法合理地选择文本。因此,控制台主机程序只是停止读取stdout/stderr输出,程序将挂起,直到用户完成操作。这可以更改,您需要关闭启用快速编辑模式选项。
请注意,这个“挂起”与程序以远高于控制台主机可以使用的速率生成stdout输出时得到的执行暂停没有本质区别。尽管这些延误是有限的。
而且这并不是用户停止程序的唯一方法,他也可以简单地按ctrl+s。按ctrl+q将再次恢复程序。

解决方法:(如果有其他方法,欢迎留言)

手动设置法

windows cmd->右键->属性->选项->编辑选项

单击左上角图标->属性->选项->编辑选项

取消 快速编辑模式

但是我将cmd设置之后,cmd是禁用了,但运行一个exe终端,发现它还是启动快速编辑模式

所以每个新exe都需手动设置。

修改程序法

windows bat

法一

头部输入以禁用

@echo off
reg add HKEY_CURRENT_USER\Console /v QuickEdit /t REG_DWORD /d 00000000 /f

REGEDIT

  • PRO:与任何常见的Windows系统兼容
  • CON:需要临时REG文件的创建
  • code(去你的脚本的开头):
if exist "%TEMP%\consoleSettingsBackup.reg" regedit /S "%TEMP%\consoleSettingsBackup.reg"&DEL /F /Q "%TEMP%\consoleSettingsBackup.reg"&goto :mainstart
regedit /S /e "%TEMP%\consoleSettingsBackup.reg" "HKEY_CURRENT_USER\Console"
echo REGEDIT4>"%TEMP%\disablequickedit.reg"
echo [HKEY_CURRENT_USER\Console]>>"%TEMP%\disablequickedit.reg"
(echo "QuickEdit"=dword:00000000)>>"%TEMP%\disablequickedit.reg"
regedit /S "%TEMP%\disablequickedit.reg"
DEL /F /Q "%TEMP%\disablequickedit.reg"
start "" "cmd" /c "%~dpnx0"&exit

:mainstart

REG

  • PRO:不需要的临时文件创建
  • CON:不可用在Windows 2000和早期没有资源工具包
  • CON:不同的版本有不同的语法

(在code以下的占)

  • code(去你的脚本的开头):
set reg50=::&set reg51=::&(reg /?>nul 2>&1 && set reg51=)
if %errorlevel%==5005 set reg50=
set qkey=HKEY_CURRENT_USER\Console&set qprop=QuickEdit
%reg51%if defined qedit_val (echo y|reg add "%qkey%" /v "%qprop%" /t REG_DWORD /d %qedit_val%&goto :mainstart)
%reg50%if defined qedit_val (reg update "%qkey%\%qprop%"=%qedit_val%&goto :mainstart)
%reg51%for /f "tokens=3*" %%i in ('reg query "%qkey%" /v "%qprop%" ^| FINDSTR /I "%qprop%"') DO set qedit_val=%%i
%reg50%for /f "tokens=3*" %%i in ('reg query "%qkey%\%qprop%"') DO set qedit_val=%%i
if "%qedit_val%"=="0" goto :mainstart
if "%qedit_val%"=="0x0" goto :mainstart
%reg51%echo y|reg add "%qkey%" /v "%qprop%" /t REG_DWORD /d 0
%reg50%if "%qedit_val%"=="" reg add "%qkey%\%qprop%"=0 REG_DWORD
%reg50%if "%qedit_val%"=="1" reg update "%qkey%\%qprop%"=0
start "" "cmd" /c set qedit_val=%qedit_val% ^& call "%~dpnx0"&exit

:mainstart

C++

搬运过来的,没测试过……

HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);

DWORD mode;

GetConsoleMode(hStdin, &mode);

mode &= ~ENABLE_QUICK_EDIT_MODE; //移除快速编辑模式

mode &= ~ENABLE_INSERT_MODE; //移除插入模式

mode &= ~ENABLE_MOUSE_INPUT;

SetConsoleMode(hStdin, mode);

参考资料

参考资料
https://stackoverflow.com/questions/21805712/windows-batch-how-to-disable-quickedit-mode-for-individual-scripts/42998160#42998160
https://www.it1352.com/329069.html
https://blog.csdn.net/gxc1222/article/details/80999234
https://blog.csdn.net/achilles_01/article/details/98849031
https://blog.csdn.net/cuiyaoqiang/article/details/103904846
https://docs.microsoft.com/en-us/windows/console/getconsolemode?redirectedfrom=MSDN

------ 本文结束,感谢您的阅读 ------

本文作者: 峡州仙士

原文链接: https://cjh0613.com/20200503win10cmd.html

声明: 如文章有更新,将先在本网站(峡州仙士之页)发布!(可百度)| 本网站所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

 

另外参考:https://www.cnblogs.com/lcawen/p/12742916.html

/// <summary>
        /// 快速编辑模式是一种很便捷的操作方式:左键选中,右键复制以及右键从剪贴板粘贴内容等
        /// 如果鼠标选中控制台界面上的内容,控制台就被阻塞了
        /// 在Windows Server 2012 及Windowns 8以上,控制台窗口的程序默认是打开“快速编辑模式”的开关的。
        /// 注册表HKEY_CURRENT_USER\Console的QuickEdit可控制全局是否打开“快速编辑模式”模式,0:不打开,1:打开
        /// 在某些场景下,控制台打印输出的时候,不系统阻塞导致程序卡住,但是windows不能针对所有命令行统一设置,只能单个程序去设置
        /// 此时,可使用如下方式:
        /// </summary>
        public static void DisableConsoleQuickEdit()
        {
            var handle = GetStdHandle(StdHandle.InputHandle);
            uint mode;
            GetConsoleMode(handle, out mode);
            ConsoleModes newMode = (ConsoleModes)mode;
            if ((newMode & ConsoleModes.ENABLE_QUICK_EDIT_MODE) == ConsoleModes.ENABLE_QUICK_EDIT_MODE)
                newMode ^= ConsoleModes.ENABLE_QUICK_EDIT_MODE;
            if ((newMode & ConsoleModes.ENABLE_INSERT_MODE) == ConsoleModes.ENABLE_INSERT_MODE)
                newMode ^= ConsoleModes.ENABLE_INSERT_MODE;
            if ((newMode & ConsoleModes.ENABLE_MOUSE_INPUT) == ConsoleModes.ENABLE_MOUSE_INPUT)
                newMode ^= ConsoleModes.ENABLE_MOUSE_INPUT;
            SetConsoleMode(handle, (uint)newMode);
        }

        public static bool SetConsoleFont(uint index)
        {
            return SetConsoleFont(GetStdHandle(StdHandle.OutputHandle), index);
        }

        [DllImport("kernel32")]
        public static extern IntPtr GetStdHandle(StdHandle index);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);

        /// <summary>
        /// https://docs.microsoft.com/en-us/windows/console/setconsolemode?redirectedfrom=MSDN
        /// </summary>
        /// <param name="hConsoleHandle">控制台输入缓冲区或控制台屏幕缓冲区的句柄</param>
        /// <param name="lpMode">模式</param>
        /// <returns></returns>
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);

        [DllImport("kernel32")]
        private extern static bool SetConsoleFont(IntPtr hOutput, uint index);

        public enum StdHandle
        {
            OutputHandle = -11,
            InputHandle = -10,
            ErrotHandle = -12,
        }

        [Flags]
        private enum ConsoleModes : uint
        {
            ENABLE_PROCESSED_INPUT = 0x0001,
            ENABLE_LINE_INPUT = 0x0002,
            ENABLE_ECHO_INPUT = 0x0004,
            ENABLE_WINDOW_INPUT = 0x0008,
            ENABLE_MOUSE_INPUT = 0x0010,
            ENABLE_INSERT_MODE = 0x0020,
            ENABLE_QUICK_EDIT_MODE = 0x0040,
            ENABLE_EXTENDED_FLAGS = 0x0080,
            ENABLE_AUTO_POSITION = 0x0100,

            ENABLE_PROCESSED_OUTPUT = 0x0001,
            ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002,
            ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004,
            DISABLE_NEWLINE_AUTO_RETURN = 0x0008,
            ENABLE_LVB_GRID_WORLDWIDE = 0x0010
        }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值