最近在运行编译好的exe文件时,发现了一个现象,就是通过cmd运行exe文件或者双击执行运行exe文件,偶尔会出现程序没有执行的情况。最开始发现这个现象时,还以为是程序出现了什么Bug。后面经过网上查询才知道,原始这一切都是控制台(cmd)模式下快速编辑模式捣的鬼。可能大家平常没有接触到,或者是没有留意。

接下来我们就一起看看什么是控制台(cmd)模式下快速编辑模式、如果解决这个问题以及简单的了解下背后的原理。

1、现象

我们先编写一段简单的代码,来复现上面说的现象。

package main

import (
"fmt"
"time"
) func main() {
for {
fmt.Println("-------------------")
fmt.Println(time.Now())
time.Sleep(time.Second)
}
}

代码很简单,就是定时向标准输出(这里就是屏幕)输出指定的内容。现象如下:

现象也如我们期望的那样。这个时候,我们用鼠标点击下控制台黑色范围,会发现屏幕没有输出内容了,程序仿佛没有执行了。现象如下:

这个时候就很奇怪了,程序运行好好的,怎么突然这样子呢?

这个时候我们将鼠标移动到黑色范围呢,然后按下 enter 键,会发现程序又开始往下执行了。现象如下:

了解了上面的现象,接下来我们看看如何解决这个问题。

2、解决办法

2.1、手动设置法

windows cmd -> 窗口白色部分,点击右键 ->默认值 -> 取消掉快速编辑模式(Q)

注意:

将cmd设置之后,cmd是禁用了,但运行一个exe终端,发现它还是启动快速编辑模式。所以每个新exe都需手动设置。

2.2、通过命令修改windows默认配置方式

这个方式,我没有测试过,大家可以自行网上搜索或看下面链接测试。

windows cmd批处理终端 快速编辑模式bug 程序运行阻塞 标题栏提示选择 需要回车继续执行

2.3、代码中禁用

package main

import (
"fmt"
"golang.org/x/sys/windows"
"os"
"time"
) func init() {
//输入模式
var inMode uint32
inHandle := windows.Handle(os.Stdin.Fd())
if err := windows.GetConsoleMode(inHandle, &inMode); err != nil {
return
}
inMode &^= windows.ENABLE_QUICK_EDIT_MODE
inMode &^= windows.ENABLE_INSERT_MODE
inMode &^= windows.ENABLE_MOUSE_INPUT
windows.SetConsoleMode(inHandle, inMode) //输出模式
var outMode uint32
out := windows.Handle(os.Stdout.Fd())
if err := windows.GetConsoleMode(out, &outMode); err != nil {
return
}
outMode |= windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
_ = windows.SetConsoleMode(out, outMode)
} func main() {
for {
fmt.Println("-------------------")
fmt.Println(time.Now())
time.Sleep(time.Second)
}
}

运行编译后的文件,这个时候再去点击用鼠标点击下控制台黑色范围,发现并不会影响程序的正常运行。

3、简单聊一聊代码中的功能以及 bitmask 的设置技巧

init 函数代码简介:

func init() {
//输入模式
var inMode uint32 //通过os.Stdin.Fd()获取标准输入的文件描述符,然后将其转换为windows.Handle类型的句柄inHandle
inHandle := windows.Handle(os.Stdin.Fd()) //使用windows.GetConsoleMode函数获取与inHandle相关联的控制台输入模式,并将结果存储在inMode中
if err := windows.GetConsoleMode(inHandle, &inMode); err != nil {
return
} //通过按位异或清除控制台的快速编辑模式
inMode &^= windows.ENABLE_QUICK_EDIT_MODE
inMode &^= windows.ENABLE_INSERT_MODE
inMode &^= windows.ENABLE_MOUSE_INPUT
//使用windows.SetConsoleMode函数将修改后的输入模式应用到标准输入句柄上
windows.SetConsoleMode(inHandle, inMode) //输出模式
var outMode uint32
out := windows.Handle(os.Stdout.Fd())
//使用windows.GetConsoleMode函数获取与out相关联的控制台输出模式,并将结果存储在outMode中
if err := windows.GetConsoleMode(out, &outMode); err != nil {
return
}
//设置控制台输出模式,包括控制台的标准输出处理模式和启用虚拟终端处理
outMode |= windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
_ = windows.SetConsoleMode(out, outMode)
}

我们debug看看程序的执行过程,前面两步如下:

执行完windows.GetConsoleMode后,inMode=503,对应二进制为:1,1111,0111。

执行完inMode &^= windows.ENABLE_QUICK_EDIT_MODE,inMode=439,对应二进制为:1,1011,0111。

1,1111,0111 = 503
0,0100,0000 = 64
异或
1,1011,0111 = 439

异或:相同为0,不同为1

这样通过异或操作,可以将bitmask(标志位)修改。

对于ENABLE_QUICK_EDIT_MODE等标志位的设定,我对它的感悟是:如果使用一个变量来控制一个软件的不用作用,比如这里是否开启快速编辑模式。我们可以使用 bitmask 来控制,bitmask 最好是按照1, 2, 4, 8 ... 这样设置,只要对应位上的数字是1表示开启,为0则表示关闭。

这样方便后续通过异或操作,设置功能是否开启,这样既简单,又直观。

https://learn.microsoft.com/en-us/windows/console/setconsolemode

Windows中控制台(cmd)模式下运行程序卡死/挂起现象解决方案(快速编辑模式)的更多相关文章

  1. C#下控制台程序窗口下启用快速编辑模式运行线程会阻止线程运行

    最近做一个小的功能,使用C#控制台程序开启一个线程进行无限循环没5秒处理一次程序,发现控制台窗口在开启快速编辑模式情况下,进行选择程序打印 出来的文字后发现线程不走了,将快速编辑模式去除后,线程就不会 ...

  2. IntelliJ IDEA在Local模式下Spark程序消除日志中INFO输出

    在使用Intellij IDEA,local模式下运行Spark程序时,会在Run窗口打印出很多INFO信息,辅助信息太多可能会将有用的信息掩盖掉.如下所示 要解决这个问题,主要是要正确设置好log4 ...

  3. MySQL-Front 出现“程序注册时间到期 程序将被限制模式下运行”解决方式

    MySQL-Front 出现“程序注册时间到期 程序将被限制模式下运行”解决方式 在用mysql-front的时候遇到显示:程序注册时间到期程序将被限制模式下运行.可以在“帮助”菜单下的点“登记”-- ...

  4. 在C#中,Windows Console控制台 设置控制台标题、禁用关闭按钮、关闭快速编辑模式、插入模式

    设置控制台标题 禁用关闭按钮 关闭快速编辑模式 关闭插入模式 设置控制台标题.禁用关闭按钮 #region 设置控制台标题 禁用关闭按钮 [DllImport("user32.dll&quo ...

  5. 非GUI模式下运行JMeter和远程启动JMeter

    JMeter是一款非常不错的免费开源压力测试工具,越来越多的公司在使用.不过,在使用过程中可能会存在一些问题,比如:GUI模式非常消耗资源,单个客户端测试无法达到目标压力.而使用非 GUI 模式,即命 ...

  6. 《机器学习实战-KNN》—如何在cmd命令提示符下运行numpy和matplotlib

    问题背景:好吧,文章标题是瞎取得.平常用cmd运行python代码问题不大,我在学习<机器学习实战>这本书时,发现cmd无法运行import numpy as np以及import mat ...

  7. OLE DB访问接口“MICROSOFT.JET.OLEDB.4.0”配置为在单线程单位模式下运行,所以该访问接口无法用于分布式

    OLE DB访问接口"MICROSOFT.JET.OLEDB.4.0"配置为在单线程单位模式下运行,所以该访问接口无法用于分布式 数据库操作excel时遇到的以上问题的解决方法 解 ...

  8. 报错解决:DENIED Redis正在保护模式下运行

    DENIED Redis正在保护模式下运行,因为已启用保护模式,未指定绑定地址,也未向客户端请求身份验证密码.在此模式下,仅接受环回接口的连接.如果您想从外部计算机连接到Redis,您可以采用以下解决 ...

  9. 教你50招提升ASP.NET性能(十一):避免在调试模式下运行网站

    (17)Avoid running sites in debug mode 招数17: 避免在调试模式下运行网站 When it comes to ASP.NET, one of the most c ...

  10. [Selenium]Grid模式下运行时打印出当前Case在哪台node机器上运行

    当Case在本地运行成功,在Grid模式下运行失败时,我们需要在Grid模式下进行调试,同时登录远程的node去查看运行的情况. Hub是随机将case分配到某台node上运行的,怎样知道当前的cas ...

随机推荐

  1. 快速上手typescript(基础篇)

    壹 ❀ 引 在javascript开发中,你可能也遇到过我这样的苦恼,在维护某段几年前的老旧代码时,我发现了某个数据加工方法fn,而且根据现有逻辑来看fn的某个参数是一个数组,因为新需求我需要对数组做 ...

  2. JS leetcode 最大连续1的个数 题解分析

    壹 ❀ 引 今天来做一道十分烦躁的题目,为什么烦躁,因为我字母写错了提交了三次错了三次!!!我的leetcode正确率大大下降!!那么这道题是leetcode的485. 最大连续1的个数,题目描述如下 ...

  3. Python subProcess库以及Popen类的使用

    subprocess库是一个十分强大且常用的库,它可以用来调用第三方工具(例如:exe.另一个python文件.命令行工具). 1.常用函数call() :执行由参数提供的命令,把数组作为参数运行命令 ...

  4. test-02-java 单元测试框架 junit5 入门介绍

    拓展阅读 junit5 系列 基于 junit5 实现 junitperf 源码分析 Auto generate mock data for java test.(便于 Java 测试自动生成对象信息 ...

  5. EmuELEC 4.3 安装和乐视手柄 LeWGP-201 evremap问题解决

    一年多前安装了EmuELEC3.9之后, 就一直没有再更新过, 平时玩玩小游戏也很正常. 昨天心血来潮想把吃灰的乐视手柄用起来, 结果发现3.9里面没有evremap 命令. 猜测可能是这个版本的问题 ...

  6. STM32F407VET6烧录出现flash download failed target dll has been cancelled

    今天在通过stlink烧录一个长时间未用的STM32F407VET6 Black Board的时候, 出现错误 Internal command error Flash download failed ...

  7. 【Unity3D】人物跟随鼠标位置

    1 游戏对象 ​ 2D动画和人体模型及动画中介绍了 Aniamtion.Animator.人体模型.人体骨骼.人体动画等基础知识,本文将通过 "人物跟随鼠标位置" 案例加强对 Un ...

  8. Java设计模式-模板模式Template

    介绍 模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern),z 在一个抽象类公开定义了执行.它的方法的模板.它的子类可以按需要重写方法实现, ...

  9. Java并发编程实例--2.获取和设置线程信息

    常用线程属性 ID: 每个线程的唯一标识: Name: 线程名称: Priority: 线程优先级,从1-10,数字越大优先级越高:不推荐改变线程优先级: Status: 线程状态,包含6种状态:ne ...

  10. golang读取用户名和密码文件并生成笛卡尔积

    密码爆破时需要读取用户名字典和密码字典来生成笛卡尔积派发爆破任务:直接读取全部字典内容到内存时成本较高: package main import ( "bufio" "f ...