Win10找不到NVIDIA控制面板 并且开机一直闪

背景

自己小米笔记本收到更新提醒,如果我就点击更新,结果重启后就出现这个问题,同时进入安全模式也会一直闪烁。(shift + 重启按钮 进入安全模式)

解决问题

  • shift + 重启按钮进入命令安全模式
  • 激活administrator 账号或者自己添加账号(选择一种就可以了,我建议直接激活,不然后面你要想要原来账号的目录内容,你要设置权限)
    • 激活管理员账号: net user administrator /active:yes
    • 创建test账号,你可以改成你账号名字: net user test /add
  • 重启电脑选择账号administrator (如果默认进去出问题的账号,你可以按ctrl + alt + delete 选择账号就可以了)
  • 这样子就进入系统,我自己卸载补丁和重装nvidia进入有问题账号还是问题,如果你没有问题,那么就解决了,如果还有问题,只通过迁移我的文档数据,来保证原来数据可以用。

总结:通过创建新账号,然后使用新账号就可以解决这个问题,这种解决办法无需重装系统,文件和数据都不会丢失。

补充资料

1:win10 进入安全模式(选择6命令安全模式,因为我用的时候安全模式也会闪)

https://jingyan.baidu.com/article/574c52190257956c8d9dc108.html

2:win10 激活管理员账号

https://www.ithome.com/html/win10/171272.htm

3:切换我的文档(指向原来的有问题的账号的文件目录,这样子就能直接用,我开始直接复制,40G复制好久没有修改目录,记住修改目录,提示你是否移动,你点击否,因为新建立账号,没有数据需要复制过去)

https://jingyan.baidu.com/article/eb9f7b6da448cb869364e8ed.html

自己花了10个小时时间解决这个问题,最终采用这个无须丢失数据和软件的方式解决了这个问题,虽然不是非常完美。写这个解决方案就是怕其他人也遇到这个问题,然后花大量时间在这个上面。以后我都不敢随便更新了,对于我这个搞开发人来说,都这么麻烦,对于小白那不是完蛋了

记住激活管理员或者创建新账号,一定要进入新的账号,否则你先进入那个错误账号,再切换到新账号也会一直闪。

electron 安装以及问题

1:因为墙的原因,我们直接npm install electron 是没有办法安装,所以我们要使用淘宝源

npm install -g cnpm --registry=https://registry.npm.taobao.org

安装cnpm模块 –g 全局安装,– registry 临时修改模块的源地址 cnmp 的模块

2:mac 全局安装 node 模块 权限问题

sudo chown -R $USER /usr/local

3:安装electron

cnpm install -g electron
//全局安装,懒得多个项目时候反复安装

4:vscode 启动

修改vscode 启动配置,如果没有,点击创建一个。在配置里面增加一行

//这行代表用当前项目的electron,如果你不是全局安装
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron"
//这个代表全局的electron
"runtimeExecutable": "electron"

客户端网页集成工具

解决问题

我们经常需要很多网页工具,比喻JSON解析,或者HTML 压缩等等,我们每次都需要打开浏览器,那么我直接有一个工具可以添加各种网页,方便我们添加,可以自定义大小

需求

  • 自定义添加网页
  • 可以自定义大小
  • 支持快捷键
  • 支持默认排序

技术方案

直接用electron就可以了,配置存取直接写文件都可以,因为简单

c++ 调用node js 回调方法

背景

node js 自己的demo ,直接把node js 回调传给c++ 然后直接回调,这样子是没有问题,但我们需要一个长期的回调,node js没有说明,网上貌似也没有对应的文档,我找了好久也没有找到。后面自己翻看node js 官网文档API ,一个个看,找到一个能用的api。

解决方法:napi_create_reference

回调对象,如果你直接保存,你下次回调的时候发现会发生错误,我分析错误信息是对象已经不能用,我看了官网文档,node js 自己管理申明周期,所以我猜测声明周期的问题,于是找他们引用的API,于是就是上面的API

napi_ref my_call_ref = nullptr;	//全局
napi_value call_back = args[1];	//传递过来的参数
status = napi_create_reference(env, call_back, 1, &my_call_ref);
//然后底层回调过来时候,调用node js回调函数就可以了
status = napi_get_reference_value(global_env, msg_recv_ref, &result);
	if (result != nullptr) {
		status = napi_call_function(global_env, global, result, 1, &buffer, &result);
		//assert(status == napi_ok); //如果上层报错,这里失败,导致程序停止
	}

上面是一个大概的代码,就是把一个回调引用是1,永远不会释放,因为我没有调用引用减少,所以永远不会释放。

备注

目前觉得小项目用node js 和 python 真的太方便,脚本写上层业务的时候,基本不好用关心语言细节,我发现好多程序员喜欢在意语法细节,我内心觉得好笑,你会用就可以了,你又不是开发语言或者写编译器的(我说那些死转语法的人,不死说不用了解语法)

c# 在子线程然回调到主线程方法

背景

我们开发代码经常面对线程的问题,多线程性带来异步方便的同时也带来稳定性问题,所以我们需要解决掉线程问题

解决方案

1:加锁

这种方案基本是解决线程的基本方法,但要求开发者对代码非常清晰,不然很容易死锁。

2:投递回调或者事件到主线程或者同一个线程里面

基本原理尽可能在同一个线程里面,那么就没有线程竞争,这种实现方式基于主线程的队列,我们常常用主线程的消息队列,c# 貌似也是类似。只要事件队列加锁就可以了,那么加锁颗粒就非常少了,我们也可以自己创建一个线程,不停等待任务,然后处理返回数据,那么数据都在所谓的业务主线程。你可以看看很多开源代码基本这么写的,android 事件也类似。android每个线程都有一个时间循环队列,比喻我们请求网络数据后,直接投递数据到android ui的主线程就可以了,那么数据就没有竞争。

3:c#的方式

SynchronizationContext 这个每个线程都有

            sync_context.Post(new SendOrPostCallback((o) =>
            {
                //执行的代码
            }), null);

Dispatcher 这个对线所有控件都会继承这个,所以你必须要保留主要界面的 Dispatcher ,但我在开发时候,如果使用不当的话会导致界面很卡,大概是代码里面反复调用导致的问题。

android DexClassLoader 加载失败

背景

自己最近想写一个APP,内部实现考虑兼容性问题,我想使用动态加载,一些核心变化的代码从服务器动态加载,这样子就不用每次都要更新APP。

动态加载

DexClassLoader: 我百度一下,基本规则是jar包通过dx处理一下,然后放在手机的sdcard里面,前提一定要给文件读写权限。

问题

我基本按照网上规则写的,但发现加载失败,我的测试手机是小米10 android 10,总是提示原始dex找不到。但文件确实存在,而且文件权限给了而且文件确实存在。

过程

  • 直接用跑模拟器 android 6 的版本上,确实可以跑起来,这说明肯定是android版本的问题,也可能跟miui的版本加强权限管理。
  • 大概解压的dex必须放在APP 自己目录,不能给外部路径,这样子为了安全问题,确实,如果dex被改成外部,就可以有权限访问内部数据。毕竟注入到代码里面去了。
  • 那么我猜测可能是加载jar路径可能也要放在APP内部,果然可以了。我放在asserts目录
  • 我猜测原因,磁盘的文件无法写入APP内部目录,因为我之前也试过/sdcard/复制到APP内部,但加载也会失败了。

node js 调用dll 方案

最近准备用node js 写一个项目,所以需要对方案进行调研,项目会用到c的dll,通过网上查资料发现基本2种方案:1:ffi 2:addon

ffi 方案

这个方案我经过一天测试,发现这个方案不行,我建议直接放弃,第一个问题安装ffi 编译不通过,通过大量资料查询因为他不支持node 12 ,我通过使用别人ffi-napi 解决这个问题,然后遇到字符串问题,以前的接口默认是wchar_t * ,发现无论使用ref-wchar_t-napi 都无法使用宽直接,后面实在没有办法,我直接转换dll的接口改成utf-8进行传递,来解决字符串问题。最恐怖我发现ffi这个方案内存泄漏实在恐怖了,我防止是我自己API的问题,我直接调用系统的API,发现如果调用很频繁会导致内存泄漏,这点我完全无法接受,因为我的程序需要长期后台运行,那么内存问题是一个恐怖的问题

ffi测试代码

k = ffi.Library("Kernel32", {
  'OutputDebugStringA': ['void', ['string']],
});


var sleep = require('sleep');
for(var i = 0 ; i < 10000; i++){
  var r = k.OutputDebugStringA('' + i);
  r = null;
}

//等待100秒,观察内存是否释放,时间可以设置更长
sleep.sleep(100);

我自己观察内存一直私有内存一直增加,循环跑完也没有回收,那么说明ffi 有内存泄漏

addon

这个用起来挺简单,本质在windows就是一个DLL,通过工具生成一个动态库工程,然后直接按照例子写代码就可以了,也方便自己写代码,这里面有几种,我目前建议采用napi这种,这种就是没有v8版本,导致编译的问题,上面ffi编译的问题就是这个原因。

使用过程:

  • 百度一个addon教程
  • 找到nodejs 官方例子,直接按照例子写就可以 https://github.com/nodejs/node-addon-examples
  • 直接跑就可以(node32 才能加载win32 dll 不然会报错),上一个方案时候就出现加载问题,目前我用node32 12的版本

备注

nodejs 开发代码确实方便很多,但从一个技术方案迁移到另外一个技术方案,成本还真不少。ffi 内存泄漏,这个就不用考虑,ffi本质也是addon技术实现,这种中间件,但网上貌似都没有遇到这个问题一样,我直接测试好几个例子都会内存泄漏。ffi可以不用自己开发一个dll来做桥梁,addon需要自己单独写一个新的dll来调用原来的dll。

输入法软件可以考虑方向

背景

输入法是我们必备的软件,国内常见的输入法有搜狗,QQ,百度等等。这类软件拥有海量的用户,但目前这么年来看很难变现。他们连常见广告变现相对克制(相对其他的软件,手机软件广告随处可见),这个原因很简单,没有合适地方显示广告,因为输入法类似插件而已,在别的软件编辑框附近出现,如果这个出现广告是非常不合适,虽然输入法在这块做了一些联想功能开发,希望能够进行更多变现。但我总感觉在沙堆上造房子感觉,小心翼翼建造,但根本做不到自己想要高度(个人感觉),长期只是吸引用户的周边产品,为其他产品提供数据或者引流的梯子。

根本问题

我觉得根本问题就是输入法寄生在别的软件上面,没有自己长期展示的界面,没法要用户看到更多,就连输入法设置界面都很少打开。

方向

搜索,更加本地搜索,要用户养成用他搜索习惯。你可能会说输入法不是早就出了联想功能,这里说搜索不仅仅联想。

场景

1:用户A想知道今天某地的天气,那么他会打开浏览器输入某地的天气,然后找到页面搜索,用户需要打开3步看到自己想要内容。如果通过输入法,我们可以通过快捷键调出输入框输入某地天气,然后自动显示对应的内容。这样子用户无需打开浏览器,就可以得到自己内容,因为输入法基本常驻内存,所以打开速度非常快,这个就是很大的优势

2:用户B想打开本地某个程序,比喻QQ或者微信。由于桌面太多图标找不到,那么输入法如果提供搜索功能找到某个软件,那么是非常顺利的事情。目前微软有类似的功能,可以同win + s 进行搜索,输入法可以把这个功能做更强,更加方便。互联网更新速度是微软不能比较的。

3:用户C如果想搜索某个问题,那么他需要打开浏览器,输入对应的问题,然后页面打开对应的内容。那么输入法可以在快捷键调出他自己输入框,然后展示一栏搜索的结果,或者直接可以进入浏览器的搜索页面,这里非常有用的,用户用起来方便,这里可以切入到自己搜索引擎,而且增加用户打开输入法的频率,进入到输入法界面

落地

用户养成用输入法的搜索习惯

  • 最开始通过积分引导用户使用开始熟悉操作
  • 更多使用搜索功能对接,输入法搜索查询IP,JSON解析,xml解析,这种只要网络,内置浏览器直接加载导入搜索内容就可以了

参考产品

可以参考utools 的一些插件功能,目前我每天使用utools,并且是付费用户。

备注

上面只是大概说了一下,只是纸上谈兵,不过我还是觉得比较落地。其实每个产品都自己优势,每个产品需要发挥他自己的优势,然后扩展出自己的天地。目前输入法大方向都是AI大数据分析,虽然没有错,但为什么不可以更加接近用户,解决更多用户需求。

SendMessage WM_COPYDATA 拒绝错误

背景

SendMessage WM_COPYDATA 我们经常用来进程通信,今天突然改了一下代码加载方式,突然发现消息无法通信,我不断的通过打印日志来确定问题,最终觉得自己代码没有问题,但就是无法发送消息到另外一个进程。突然想到GetLastError() 看一下有什么错误,通过打印发现出现错误5,然后通过vs 带的错误查询,发现是拒绝错误。

解决方案

通过GetLastError, 我的脑海大概猜测是权限问题,于是搜索SendMessage WM_COPYDATA 拒绝错误,然后我找到这篇 https://blog.csdn.net/aa1991/article/details/19504557 ,固然验证是权限问题。如果是按照文章调用 ChangeWindowMessageFilter(WM_COPYDATA, 1); 就可以了

总结

排错需要更加系统化,尽可能了解不同知识点,更重要是思考方式,学会不断调节

PE加载器,DLL内存加载器

背景

我最近研究了DLL内存加载,网上找了好久代码,基本的原理差不多,自己稍微总结一下。

逻辑

  • 内存读取PE,按照PE格式进行加载(任何一本介绍PE的书籍都可以看有关知识)
  • 修复重定位表(这点非常重要,我开始不明白他怎么修复定位表)
  • 修复定位表
  • 其他细节(tls回调,修改PEB)
  • 调用入口启动

疑惑

1:怎么执行代码?

我们创建内存,然后复制PE到内存中,然后直接调用,但一些变量地址或者函数地址是以va(虚拟地址)直接访问,这些地址固定死的,但加载内存时候,基本不可能是原来的基地址,那么这些地址就是错误地址。那么这些地址要被修改,所以正常加载DLL或者EXE(正常启动EXE基本地址不会变化),如果模块的基地址变化都需要修改地址不然会崩溃。那重定位表记录原来硬编码的地址,我们遍历所有地址修复就修改掉。

2;兼容性

因为毕竟是我们人工模拟加载,那么可能缺失很多环境,导致异常。程序异常退出,这种只能通过OD动态调试分析,然后结合进程,线程有关知识来进行分析。最快就拿别人开源代码跑,因为这种都是经验,如果对这块没有研究,突然去研究感觉有点懵。

代码

1:一份简单代码

2:一份比较稳定,代码非常漂亮

https://github.com/polycone/pe-loader

可以加载MFC,代码优美,多了PEB修复,TLS回调等,只能启动标准的PE,不支持c#.可以正常启动酷我。酷狗启动不了,网易云音乐可以,QQ可以启动但看进程明显自动创建进程来实现。PC微信可以。整体看稳定系还是非常高,而且如果我们自己用,被启动程序我们也可以改,来适配稳定系。

加载DLL

加载DLL比EXE简单一些,不用修复PEB,我暂时没有测试DLL,但应该差不多。

作用

这个看每个人用途,这个技术和android插件技术类似,android多开就是插件技术,稳定性就要看模拟的程度了,这样子技术需要大量的用户测试反馈来排除一些坑。

备注

1:我本想顺着分析loadlibray,发现对于我非内核开发或者非专门逆向分析来说有点难,这种需要经验分析,有一些书籍有涉及,但比较少。

2:大量这几天查看和阅读大量知道PE加载器的核心知识点。

3:找相关代码 google : pe loader github 就可以找到很多代码。