Waxxh's Blog https://waxxh.me/ zh-CN 御宅之力,终破次壁 Tue, 05 Apr 2022 21:11:00 +0800 Tue, 05 Apr 2022 21:11:00 +0800 三年又三年 https://waxxh.me/archives/ThreeYearsAfterThreeYears.html https://waxxh.me/archives/ThreeYearsAfterThreeYears.html Tue, 05 Apr 2022 21:11:00 +0800 Waxxh 转眼间博客已建立1973天,三舍四入就是六年了。期间一共写了现存155篇水文,距离上一次水文已过去整整653天,也就是从毕业后北京第一家公司跳槽到上海第二家公司后的第一个月就开始断更了。

很忙吗?其实不然,965工作制,刚开始半年很少加班,项目进度不赶,也就想攒调休时加班换换,到了21年年后出差香港就开始忙起来了。

很忙吗?也没有,就是工作日晚上时不时加加班,很少周末加。从后半年开始,开始对接不断更改、细节不明确的需求,不规范又反复修改的设计文档,又时不时需要翻看20年前的屎山来参考开发,终于积累到了上班如上坟的阶段。下班时间完全不想再接触工作上的事,自我学习、沉淀也变得开始排斥,似乎进入了另类的舒适区。

疫情,一战就是三年,灾害下各种魔幻离谱的事件已在现实中发生,普通人想保全自己更是难上加难,活下去已成为逆周期的永恒主题。小区路边的门面转租不断,连好吃实惠不愁客的那家兰州牛肉面都跑了,一线城市都已这样其他都不用想象了。

今天是鸳鸯锅式封城居家的第5天,没有解封通知,看来是要继续封着了,希望这该死的疫情尽快结束吧。普通人,唯有养好本钱,跟上趋势,认清形势,稳中求进一途了。

]]>
12 https://waxxh.me/archives/ThreeYearsAfterThreeYears.html#comments https://waxxh.me/feed/archives/ThreeYearsAfterThreeYears.html
春夏之交,诚恳地生活就很好 https://waxxh.me/archives/day-by-day.html https://waxxh.me/archives/day-by-day.html Thu, 30 Apr 2020 23:53:00 +0800 小仙女

2020的不平凡,似乎冥冥之中早已注定。
岁月无虞,疫情的突发,见证了人生百态。与此同时,也在平淡的岁月里悟出了很多——关于生活,关于陪伴,关于未来···

隔离,成为了我们生活的多数,带着未知与无常。切断了和外界的联系,却也发现了生活。

快节奏的时代似乎慢了下来,世界静默如初。曾经忽略遗忘掉的东西,也可静下心,在时间更迭中渐渐拾起;过去,我们对平常的日子或许有些厌倦,但面对着生命的脆弱、有界限,现在我们唯一能做的就是好好珍惜它,热爱它,拥抱它。从日出到日落,记住每一个日子,这都将成为生命里不可复制的那一天,和自己安静相处,诚恳的生活。

我们每个人都在人生的湍流中冲刷着,山一程,水一程,一步步的褪去了幼稚懵懂,逐渐长大成熟;“故乡”这代名词,在记忆中也愈发的模糊,渐行渐远。它,是我们年少时极力想要挣脱逃离的地狱;也可能会是我们年老时再也回不去的天堂。请不要总以为来日方长,还有很多时间停留在故乡,陪伴着亲人。人在光阴似箭流,当父母的青丝中掺了白发,我们才逐渐意识到陪伴的时间是多么的短暂,所以,在自己还可以有些许自由主动权的时候,请多抽出些时间陪伴他们。若干年后,当我们在城市的喧嚣中向上攀爬,终于不知疲倦后,蓦地回首,原来故乡是根本剪不断的,它连着血脉,扎根于心,时刻给予我们奋发的动力,让我们向前走的更加坚定,努力去追寻充沛的人生。

我曾以为自己被限制禁锢着,以为世界不曾在自己身上投过目光,那尚待发生之事,总是接近想象的那么完美;也是那未发生的,总有最多的不安,但“可能”仍是一个美妙的词,极致而又残缺。多给自己穿上坚持的盔甲,一点一点成为更好的自己,未来很长,只要心中始终怀有那份期许与美好,不断地去积累,谦逊的学习,相信以后的日子里,放眼望去,全部都是自己喜欢的人和事。

2020年悄然而逝,我们走过了烟花三月,人间四月天,又到了似水的季节——五月。新月伊始,更要好好活在当下,努力努力再努力。

生活的同时,也不要忘记感谢相遇;感谢陪伴;庆幸懂得;庆幸拥有;庆幸身边有一个如春日暖阳般温暖的男人,虽不会轰轰烈烈,不会甜言蜜语,却会用日复一日,平淡如水的爱恋滋润着每一天的开心、疲惫、感动······愈发地让我着迷,心生欢喜。

我们在各自的忙碌中,彼此挂念。想起他时,深藏于内心深处的那份喜欢又再次出现;如约而至,虽等得漫长,却从未辜负。待到相逢,真想和他说一声:别来无恙,我最亲爱的。♥

愿我们在自己的时区,诚恳地活着,等待所有的美好开花结果。

愿我们相信天色温柔,未来会很好!

]]>
8 https://waxxh.me/archives/day-by-day.html#comments https://waxxh.me/feed/archives/day-by-day.html
Win10系统 软件无法随系统自启动的问题 https://waxxh.me/archives/Software-self-start-problem.html https://waxxh.me/archives/Software-self-start-problem.html Tue, 21 Apr 2020 18:39:00 +0800 Waxxh 大多数时候,我们都是禁止软件随系统自启动,以免占用系统资源,拖慢系统启动速度。但有些时候,一些好用、需要常驻的工具软件我们却希望它们随系统自启动,带来方便与快捷,比如截图、翻译、邮箱等软件。然而在 Win10 系统以管理员身份运行的软件却没法通过正常的方式让它随系统自启动。

软件设置开机自启动的方式一般有两种,第一种是直接把想要自启动的软件的快捷方式丢到 C盘的启动文件夹里,例如全路径:C:\用户\你的账号名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

AppData 文件夹是隐藏的,需要把文件浏览窗口——查看——隐藏的项目 勾选上了才显示。

第二种是设置注册表 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run ,手动设置的话是新建一个字符串值,把想要自启动的软件 exe 路径粘贴到数值数据那保存了就好,如果需要最小化显示在任务栏,在后边加上 -min 参数。

软件自带的随系统自启动功能大多也是通过这种方式实现的,比如 Qt 是使用 QSettings 实现:

void MainWindow::on_checkBox_clicked(bool checked)
{
    const QString regPath="HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
    QString appPath = QApplication::applicationFilePath().replace("/", "\\");//获取软件完整目录,替换/为\\,转义后为正确路径形式
    QString appName = QApplication::applicationName();//获取软件名称,不获取也行,后边自行设置名称
    QSettings settings(regPath,QSettings::NativeFormat);  //需要 #include <QSettings>
    if(checked)
        settings.setValue(appName, appPath);//写入注册表
    else
        settings.setValue(appName, "");//取消勾选则设置数值数据为空,即不自启动
}

最后问题来了,以管理员身份运行的软件通过这两种方式也无法自启,大概是因为 UAC(User Account Control,用户帐户控制)的原因,Win8 及之后的版本,微软为了提高系统安全,对系统做了许多限制。那就手动解决一下吧,我们还可以通过批处理脚本或 vbs脚本解决无法自启动问题。

(1)使用批处理脚本解决,缺点是每次开机会产生一闪而过的黑框框,不美观。新建一个文本文档,添加启动软件命令,要启动多个软件就依葫芦画瓢多放几行命令:

start /d "D:\Tools\Snipaste" Snipaste.exe

保存,记得另存为看看是否默认显示编码为 ANSI ,如果不是就需要另存为 ANSI 了,不然会乱码也会导致命令无法执行。

然后把 xxx.txt 重命名为 .bat 后缀,需要把文件浏览窗口——查看——文件拓展名 勾选上了才显示并能更改后缀。
最后如方式一把它丢到C盘的启动文件夹里就OK了。

(2)使用 vbs 脚本解决,没有黑框框,缺点是可能导致有些软件保存的设置失效恢复了默认,视软件而定。一样是新建一个文本文档,添加启动软件命令,多个文件则多个 ws.run... ,一样需要另存为确定是否为 ANSI 编码,然后重命名为 .vbs 后缀,最后也丢到C盘的启动文件夹里:

Set ws = CreateObject("Wscript.Shell")
ws.run "D://Tools//SnipasteX64//Snipaste.exe",vbhide
ws.run "D://Tools//其他软件1.exe",vbhide
ws.run "D://Tools//其他软件2.exe",vbhide

如果使用方法(2)导致软件保存的设置失效恢复了默认,只能采用套娃的方法了:
使用(2)vbs 脚本启动批处理脚本 .bat,然后再使用(1)批处理脚本启动软件,只需要把 vbs 脚本丢到C盘的启动文件夹里。

]]>
0 https://waxxh.me/archives/Software-self-start-problem.html#comments https://waxxh.me/feed/archives/Software-self-start-problem.html
截长图 滚动截图工具 FastStone Capture https://waxxh.me/archives/FastStone-Capture.html https://waxxh.me/archives/FastStone-Capture.html Fri, 17 Apr 2020 14:52:00 +0800 Waxxh 作为截图工具的补充,可以使用 FastStone Capture ,可以和 Snipaste 互补,它拥有 Snipaste 没有的滚动截图、自定义形状区域截图功能,另外还有屏幕录像功能,鼠标跟踪、高亮这些基本特性都有。

同样可以设置快捷键使用,默认截图是自动保存,可以设置为到编辑器、到剪切板等等。

---官网下载

]]>
10 https://waxxh.me/archives/FastStone-Capture.html#comments https://waxxh.me/feed/archives/FastStone-Capture.html
好用的截图工具 Snipaste https://waxxh.me/archives/snipaste.html https://waxxh.me/archives/snipaste.html Wed, 15 Apr 2020 23:21:00 +0800 Waxxh 一直在使用的截图工具 Snipaste ,拥有快捷键截图、贴图、屏幕取色、个性指向箭头、马赛、涂鸦、文字等功能,十分强大。

如果说还缺啥那就是滚动截图截取长图功能,这个可以使用 FastStone Capture 作为补充工具,滚动截图功能还是比较好用的。

下载解压,记得设置以管理员方式运行,不然在有些软件界面无法截图,设置开机启动更加方便。

---官网下载

]]>
7 https://waxxh.me/archives/snipaste.html#comments https://waxxh.me/feed/archives/snipaste.html
日常——只有名字很日常 https://waxxh.me/archives/My-Ordinary-Life.html https://waxxh.me/archives/My-Ordinary-Life.html Fri, 10 Apr 2020 21:48:00 +0800 Waxxh 我們所经历的每个平凡的日常,也许就是连续发生的奇迹 〉〉〉传送门

]]>
3 https://waxxh.me/archives/My-Ordinary-Life.html#comments https://waxxh.me/feed/archives/My-Ordinary-Life.html
服务器莫名的内存高占用 导致 MySQL 停止运行问题 https://waxxh.me/archives/memory-and-mysql-boom.html https://waxxh.me/archives/memory-and-mysql-boom.html Wed, 08 Apr 2020 09:26:00 +0800 Waxxh 这问题是年后开始出现的,服务器内存占用越来越高,一度达到90%,最后 MySQL 都停止运行了。贴吧签到的数据库用户 ID 这一项也丢失了,导致无法签到,断签了好些天,被提醒才发现,要挨打的。幸好设置了自动备份,把数据恢复,然后提高了签到频率,没想到后边反复出现了几次,不得不重视。

出现了几次就不是偶然了,最后每次都飙到85%,只能重启服务器解决。第一次出现时以为是 MySQL 数据库的自身问题,可能因服务器内存小而崩溃,实际1.8G 的运行内存不大不小的。查了数据库日志发现数据库因分配内存不足而启动失败,用 top 命令也查了下,内存高占用的前 20 有 MySQL,是个大头,于是添加了 2G 的 Swap 虚拟内存,再添加了数据库进程守护,计划任务每5分钟运行一次,检测到 MySQL 不运行了就重新启动。

pgrep -x mysqld &> /dev/null
if [ $? -ne 0 ];then
        bash /www/server/panel/script/rememory.sh   
        /etc/init.d/mysqld start      
fi

结果过了些天问题依旧出现了,4G 内存也不够耗。这就有点莫名其妙的,之前一直运行好几年稳如狗的,怎么突然就这样呢?回想一下自己的操作,除了升级高版本宝塔面板好像就没了,升个大版本应该不会突然占用飙升吧,查进程看面板占用也才几十 MB ,到论坛也没见有人反馈,说明不是这个原因。

最后用 ps 命令仔细查看了所有进程,终于发现了问题的源头,是贴吧签到的定时任务和 php-fpm 。如果需要不间断地自动签到,那就得不停地访问执行签到的 do.php 页面。进程中发现了几十个正在运行的 do.php 和php-fpm 进程。

原来设置的是一分钟执行一次的 crontab ,后来似乎是嫌签到太慢,我就就按着查到的方法改为 10 秒执行签到一次:

php /www/wwwroot/qiandao/do.php    
sleep 10; 
php /www/wwwroot/qiandao/do.php
sleep 20; 
php /www/wwwroot/qiandao/do.php
sleep 30; 
php /www/wwwroot/qiandao/do.php 
sleep 40; 
php /www/wwwroot/qiandao/do.php
sleep 50;
php /www/wwwroot/qiandao/do.php

面板提供的计划任务功能最小只能 N 分钟执行,就查了下,了解到可以用 sleep 来实现。虽然知道在 C++ 程序中长时间延迟不能用 sleep ,都是用不会导致程序假死阻塞的定时器,但在这计划任务中PHP用应该没问题吧?还是 to young to simple 了,去除 sleep ,改回一分钟执行一次,重启服务器,再也没出现内存爆满的问题了,回到了以前正常占用内存60%左右。

最开始只用了 top 查内存高占用的前 20 进程,所以没发现是 do.php 和 php-fpm 的原因。一个进程只占了不到 9 mb ,虽然PHP管理中限制了 php-fpm 最大子进程数是50个,但到50个后,do.php 进程也达到 50 ,两个加起来占用就飙到 900 MB 了,妥妥地爆满。

正常我的网站 PHP 需求 是不会产生几十个进程的,是使用 sleep 导致了这个问题。原因大概是采用 FPM 管理 PHP 进程,由于 sleep 导致阻塞等待,FPM 实际分配了过多子进程,然后我的 PHP 并发方案是设置的 2G ,问题就这么产生了。

总结:编程不专业,程序两行泪。

]]>
2 https://waxxh.me/archives/memory-and-mysql-boom.html#comments https://waxxh.me/feed/archives/memory-and-mysql-boom.html
VS 十分好用的工具 dumpbin 命令 https://waxxh.me/archives/VS-dumpbin.html https://waxxh.me/archives/VS-dumpbin.html Thu, 02 Apr 2020 21:39:00 +0800 Waxxh VS 自带的 dumpbin 命令工具可以通过简单的命令查找出某个程序所依赖的动态库(.dll),也可以查看某个动态库含有哪些接口,或者该动态库属于 32位 还是 64 位的。还有很多功能,都是日常工作能用得上的,甚是方便。

通过开始菜单或直接到安装目录,找到 VS2015 开发人员命令提示 运行,出来的黑框框输入对应命令即可查询。

(1)查看程序有哪些依赖的动态库,命令头 dumpbin /dependents + 空格 + 程序路径:

dumpbin /dependents C:\Windows\regedit.exe

Image has the following dependencies 列出的是程序启动时就加载的动态库,即隐式加载;
Image has the following delay load dependencies 列出的是程序动态加载的动态库,即显式加载。

(2)查看动态库有哪些函数接口,命令头 dumpbin /EXPORTS + 空格 + 程序路径:

dumpbin /EXPORTS C:\Windows\twain_32.dll

(3)查看静态库(.lib)有哪些函数接口,命令头 dumpbin /LINKERMEMBER + 空格 + 程序路径:

dumpbin /LINKERMEMBER D:\Users\Desktop\dll.lib

(4)查看动态库是 32 位还是 64 位,命令头 dumpbin /headers + 空格 + 程序路径:

dumpbin /headers C:\Windows\twain_32.dll

]]>
0 https://waxxh.me/archives/VS-dumpbin.html#comments https://waxxh.me/feed/archives/VS-dumpbin.html
限制 MFC 程序只能运行一个 https://waxxh.me/archives/MFC-only-one-can-run.html https://waxxh.me/archives/MFC-only-one-can-run.html Mon, 30 Mar 2020 13:40:00 +0800 Waxxh 有时候会有这样的需求:让某个程序只能运行一个,不让它能打开多个,即多开,多进程。使用 CWnd 类的几个函数即可实现。

上图是 VS 自带的 Spy++ 工具,使用它可以查看Windows操作系统中运行的程序窗口、消息、进程、线程信息。一个含窗口的应用程序总是有窗口信息的,使用 FindWindow 函数可以查找系统中是否含有指定窗口类名和标题名的程序在运行,如返回非空句柄则说明该程序已运行,然后再做对应判断即可实现单进程程序。

可以直接使用 Spy++ 找到窗口的标题,也可以到资源视图中自定义一个,然后在 InitInstance() 初始函数中加入对应判断即可:

CWnd *pWndPrev, *pWndChild;//定义句柄指针
pWndPrev = CWnd::FindWindow(NULL, _T("MFCApplication1"));//第一个参数是窗口类名,第二个参数是窗口标题
if (pWndPrev != NULL)//返回句柄不为空说明该程序已运行
{
    //AfxMessageBox(_T("程序已运行!"));//可以选择先提示程序已运行
    pWndChild = pWndPrev->GetLastActivePopup();//获取该程序最近处于活动状态的弹出窗口
    if (pWndPrev->IsIconic())
        pWndPrev->ShowWindow(SW_RESTORE);//如果窗口已经最小化就恢复显示窗口
    pWndChild->SetForegroundWindow();//激活该程序窗口到前台显示
    return FALSE;
}
]]>
0 https://waxxh.me/archives/MFC-only-one-can-run.html#comments https://waxxh.me/feed/archives/MFC-only-one-can-run.html
MFC 开发中一些报错的解决方法 https://waxxh.me/archives/MFC-errors.html https://waxxh.me/archives/MFC-errors.html Wed, 25 Mar 2020 14:31:00 +0800 Waxxh 万事开头难,新入坑时,很多简单的报错都要花较长的时间精力去解决,身边没有大佬带也只能时间换经验,自己查找解决方法。为了减少时间的无效消耗,必须得系统地学习基础,视频教学是比较适合新入坑的,然后再转到书籍。C++ 比较难,加上老旧的 MFC 就变得难上加难,让你左右为难。总结一下这些报错的解决方法,以祭奠曾因此逝去的青春。

(1)error C2440: “初始化”: 无法从“const char [x]”转换为 xxx wchar xxx
比如:

CString str = "Hello, world!";

就会报这样的错误,使用 _T() 把这类非变量字符串包括即可解决,使用 TEXT() 或者 _TEXT()是一样作用 。

CString str = _T("Hello, world!");

_T() 是一个宏,当处于 Unicode 字符集下自动加 L() ,加 L() 定义字符串为 Unicode 编码。虽然把项目改成多字节可以直接不用这么麻烦,但为了兼容,不出现乱码等问题,还是建议使用 Unicode 统一码。

(2)MFC 程序打开报错,提示:由于找不到MFC42D.DLL,无法继续执行代码。重新安装程序可能会解决此问题。
① 这类提示缺失 DLL 动态库 带有 mfc、ms、vb 等相关字母的是微软类库,一般是编译程序时没有选择“在静态库中使用MFC”,在其他电脑运行时出现。

如果选择“在静态库中使用MFC”编译的程序,还是出现此类报错,那就是系统有缺失,可以搜索微软常用运行库合集 ,安装即可解决。

② 如果按照 ① 的操作后还是出现 DLL 缺失报错,那就不是微软常用运行库了,可能是项目另外引用的,可在项目中查找或者搜索下载过来,放在和 exe 程序同一路径中,比如同一文件夹,具体视源码中的调用路径而定。

(3)Debug 调试运行时提示 xxx occcont.cpp line:925 错误

这类一般是 程序使用了某个 OCX 控件,但是在本电脑上未注册该控件。找到该控件,以管理员方式运行 CMD 命令注册即可,注意改为 OCX 控件所在的对应路径:

regsvr32 D:\Users\Desktop\xxx.ocx

如果提示注册成功后,还是出现此错误,那大概是 Debug 调试运行时选错平台了,比如 x86 的项目,运行成了 x64 , 控件也分 32 位和 64 位。

(4)使用高版本的 VS ,升级 VS 工程后,资源视图的 .rc 资源打不开,报错 error RC2104:undefined keyword or key name: xxx
编辑.rc 源文件,加入头文件: #include <windows.h>

(5)error C4996: 'scanf': xxx
C4996 错误是使用了 C 语言标准的函数,在高版本 VS 中会由于不安全报错,使用安全函数 scanf_s 即可解决,在原函数后加 _s ,其他如 printf、strcpy 也一样,虽然可以添加预处理器命令或宏定义屏蔽掉来解决,但不建议这么做。

(6)error C2065: “xxx”: 未声明的标识符
①一是因为未申明的变量直接使用产生,比如直接使用了 int型的 num ,而没有提前申明 int num;
②二是未定义命名空间,使用 cout 、cin 这类没有先定义。

#include "stdafx.h"
#include <iostream>
//using namespace std; //①未定义命名空间会报错,偷懒用法,大型项目不建议用,建议使用②

int main()
{
    int num;   //未申明直接使用 num 会报此错误
    num = 3;
    std::cout << "dd" << std::endl;// ②定义命名空间,加 std:: 

    return 0;
}

(7)error LNK2019: 无法解析的外部符号 xxx1 该符号在函数 "xxx2" 中被引用
这种情况是在头文件申明了函数 xxx1 ,但未定义,直接在 xxx2 中使用了,解决方法是在对应 cpp 源文件定义 xxx1 函数。
如果是隐式调用DLL时报错,那看看是否忘了包含对应 lib。

(8)串口通讯使用 MSCOMM32.OCX 控件,大于 16 的串口端口号会无法正常通讯, 打开时报错无效串口号: invalid port number
控件自身限制可最大端口号为 16,需使用十六进制编辑器或直接用 Sublime 等编辑器打开 ocx,在 1179 行找到 "3d10",将其中的 10 改成 FF ,即可支持最大端口到 255 ,足够应付任何情况了。

]]>
0 https://waxxh.me/archives/MFC-errors.html#comments https://waxxh.me/feed/archives/MFC-errors.html