首页 > 系统相关 >Windows中控制台(cmd)模式下运行程序卡死/挂起现象解决方案(快速编辑模式)

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

时间:2024-03-22 18:55:50浏览次数:33  
标签:ENABLE Windows cmd inMode windows 模式 控制台

最近在运行编译好的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

标签:ENABLE,Windows,cmd,inMode,windows,模式,控制台
From: https://www.cnblogs.com/huageyiyangdewo/p/18089068

相关文章

  • Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately
    VSCode+MSBuild开发过程中出现如下警告:Pleasedefine_WIN32_WINNTor_WIN32_WINDOWSappropriately处理方法为,在c_cpp_properties.json文件中加入"_WIN32_WINNT>=0x0A00"的定义,配置如下:{"configurations":[{"name":"Win32",......
  • 戴尔windows服务器安装双系统报错For a UEFI installation, you must include an EFI
    安装centos7.9的分区时候,提示:ForaUEFIinstallation,youmustincludeanEFISystemPartitiononaGPT-formatteddisk,mountedat/boot/efi网上有好多人说修改bios,用常规的usb去启动,不要UEFI的方式,但我的windows系统已经是GPT格式,且原来就有一个EFI,所以我还是用UEFI的方......
  • Redis的安装和部署教程(Windows环境)
    一、安装Redis服务1、下载Redis压缩包以下这个是我网盘里面的(这个是v8.0版本的,支持导入.rdb数据文件)链接:百度网盘请输入提取码提取码:x0f1--来自百度网盘超级会员V5的分享2、解压到文件夹将下载的压缩包解压到指定的文件夹中,如:D:\redis,内容如下:3、修改redis.conf......
  • 【转】[C#] 单例模式
    来自:阿里的通义灵码在C#中,单例模式实现线程安全时通常会采用双重检查锁定(Double-CheckedLocking,DCL)的策略来确保只创建类的一个实例,并且这个过程是线程安全的。两层lock的设计是为了减少获取锁的开销,尤其是当类的实例已经被初始化的情况下。以下是一个使用双重检查锁定的C#......
  • 揭密网络犯罪商业模式及其价值链
    基于网络的犯罪活动越来越多,网络犯罪已经形成了一套庞大商业模式,网络犯罪即服务,通过购买服务可以从事各种网络犯罪活动,也正是因为这种商业模式的出现,导致网络犯罪成本越来越低,实施网络犯罪的团伙也在不断增加,基于这种商业模式,任何人都可以通过地址网络犯罪组织购买相应的服务,从......
  • Linux 多网卡做bond模式
    bond概念将两张网卡绑定,共用一个IP,实现冗余效果。实际上Linux双网卡的绑定模式有7种,而在这里常用的是active-backup,一个设备如果只有一个网卡,那么当这个网卡损坏时设备的网络就会瘫痪。绑定接口的作用就是让多个物理网卡服务于一个IP地址,使得这个网络的抵抗性强。一个设备只......
  • Redis系列之高可用集群模式介绍
    Redis系列之高可用集群模式介绍1.Redis主从模式1.1什么是主从模式?主从模式,是redis集群最基本的模式,主库负责读写,从库负责读。主库的数据会同步到从库,但是从库写的数据不会自动同步到主库,除非用写脚本等方式手动同步。这种模式应急能力比较差,假如出现宕机的情况,需要手动......
  • Windows server 系统 AD域、加入域——无法加入 Windows Server 2012 R2 或 Windows 7
    目录前言症状原因解决方案更多信息前言       大家好,我是你可知这世上再难遇我 创作者,最近工作中做项目的时候,做Windows服务器数据迁移,前期得加入前服务器的AD域控中,经过一天从早到晚,最终在下班后找到解决方法,现在分享一下我当时最后的解决问题的方式!......
  • ETL的全量和增量模式
    在当今信息爆炸的时代,数据管理已经成为各行各业必不可少的一环。而在数据管理中,全量与增量模式作为两种主要的策略,各自具有独特的优势和适用场景,巧妙地灵活运用二者不仅能提升数据处理效率,更能保障数据的准确性。 一、ETL同步方式详解1.全量同步:优势:全量同步可以确保目标系统......
  • Python和Pycharm在windows环境下的安装
    Python和Pycharm在windows环境下的安装找到python:登录官网www.python.org在主页找到Downloads选择对应电脑系统---->找到你要下载的版本下载即可找到Pycharm:登录网站https://www.jetbrains.com/pycharm/download/#section=windows---->开发人员选项---->pycharm---->选择......