最近碰到一个问题,是关于芯片测试过程的。这颗芯片被用在笔记本的端口上。笔记本的客户那边会进行一个压力测试,测试内容是频繁地进行电脑电源状态的切换,包括 S0(正常使用的开机状态)、S3(睡眠模式)、S4(休眠模式)以及 S5(关机模式)。

主要是在压力测试过程中,客户发现了芯片会出现不正常的死锁。客户把机台寄了回来,接下来要如何复现呢?客户那边有自己的一套压力测试系统,但是会测试很多东西,不太便于给我们,并且每一次循环耗时比较长。那么,是否可以自己搭建一套能够控制电脑睡眠、休眠、关机以及唤醒的程序呢?
上面讲述的是一个应用背景,告知大家实际上是存在需求的,只是在平时不太会使用,所以将其记录了下来。
首先,将电脑从开机状态 S0 切换至 S3 是比较容易实现的。其次,把电脑从开机状态 S0 切换到 S4 也是比较容易实现的。再者,把电脑从开机状态 S0 切换到 S5 同样是比较容易实现的,见下面代码:
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre class="syl-page-code"><code>Application 设置挂起状态为电源状态挂起(PowerState.Suspend),设置为假(false),设置为假(false);这是从 S0 进入 S3 的操作。 Application 设置挂起状态,状态为电源状态休眠,第二个参数为 false,第三个参数为 false;此操作是从 S0 进入 S4。 Process.Start 函数用于启动一个新进程。其中,第一个参数 "shutdown" 表示要执行的操作是关机。第二个参数 "/s /t 0" 中,"/s" 的意思是要关闭计算机,"/t 0" 表示设置关机的延迟时间为 0 秒,即立即关机。 参数 /t 0 的含义是向计算机传达在 0 秒过后执行命令这一信息。 Process.Start("shutdown", "/r /t 0"); 此操作中 /r 参数的含义为要重新启动计算机。</code></pre></p>如果调用上述语句就能达成从 S0 到其他电源状态的转变,那么反过来要如何唤醒呢?
唤醒存在难点。处于 S3、S4 以及 S5 的状态时,我的上位机程序不会运行。所以,上位机软件的定时唤醒无法工作。那么笔记本客户那边是如何操作的呢?他们通过底层的 EC 控制来显示上述功能。然而,我们不知道底层 EC 的接口,并且我们需要一个通用的程式,那该怎么实现呢?
在笔记本的设计里,S3、S4、S5 通常不是所有东西都会关闭。通常会有一个硬件定时器处于开启状态。如果我们能够操作这个定时器,那么是否就可以实现我们所想要的功能呢?
可以调用以下两个函数,即某个函数和另一个函数,这两个函数能够控制电脑中所开启的硬件定时器,至于这个硬件定时器究竟是位于 CPU 内部还是 EC 内部,我并不知晓,也未曾进行过研究,如果有精通此领域的大神进行过研究,可以留言,我也可以借此学习学习。
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre class="syl-page-code"><code>[DllImport("kernel32.dll")] 公共静态外部方法 SafeWaitHandle 创建可等待定时器(IntPtr lpTimerAttributes,布尔值 bManualReset,字符串 lpTimerName); 在“kernel32.dll”中进行 DllImport 操作,并且设置了 SetLastError 为 true 。 [return: MarshalAs 为 UnmanagedType.Bool 的形式] 公共静态外部方法 SetWaitableTimer 接收一个 SafeWaitHandle 类型的参数 hTimer,一个引用类型的 long 类型参数 pDueTime,一个 int 类型的参数 lPeriod,一个 IntPtr 类型的参数 pfnCompletionRoutine,一个 IntPtr 类型的参数 lpArgToCompletionRoutine,以及一个 bool 类型的参数 fResume,并返回一个 bool 值。该方法用于设置可等待定时器。</code></pre></p>另外,有一点需要说明,使用这个定时器是有条件的。首先,你得先设置笔记本,即“Panel>Power>Plan>Power>Sleep>Allow Wake”,以实现定时器唤醒功能。其次,“Panel>Power>Plan>Power>Brad/>a on”,这一步是关闭唤醒需要密码。
完成上述设置后,电脑能够从 S3、S4、S5 唤醒。然而,在我使用的过程中,遇到了一个问题,即唤醒之后屏幕不亮,会让人误以为没有唤醒。所以,我增加了控制鼠标移动的命令,这样一来,唤醒之后屏幕就会亮起。
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre class="syl-page-code"><code>[DllImport("user32.dll")] 公共静态外部方法 mouse_event,该方法接收一个 32 位整数 dwFlags,一个 32 位整数 dx,一个 32 位整数 dy,一个 32 位整数 dwData,以及一个无符号指针 dwExtraInfo 作为参数。 调用 mouse_event 函数,传入参数 0x0001、0、1、0 和 UIntPtr.Zero,用于模拟鼠标操作。 调用 mouse_event 函数,其参数为 0x0001、0、-1、0 和 UIntPtr.Zero 。 该函数用于模拟鼠标操作,这里的第一个参数 0x0001 可能代表某种特定的鼠标动作。 第二个参数 0 表示鼠标的水平移动量。 第三个参数 -1 表示鼠标的垂直移动量。 第四个参数 0 可能与鼠标的其他相关设置有关。 最后一个参数 UIntPtr.Zero 也可能在鼠标事件的处理中起到特定的作用。</code></pre></p>另外需注意,在笔记本从 S0 到 S3/S4/S5 再到 S0 的循环中,S0 以及 S3/S4/S5 这几种状态的停留时间需足够长。因为每台笔记本完全进入各状态的时间不同,例如我自己的笔记本,这些状态的停留时间至少要 20 秒。否则,笔记本尚未完全进入就退出,会致使电脑关机,而此时笔记本还未被唤醒,从而导致程式死锁。而新的刚买的笔记本,只需要设置10s即可完全进入。
废话不多说,直接上代码:
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre class="syl-page-code"><code>using System; 系统使用了一系列的集合类型,这些集合类型包含了多个元素,它们共同构成了特定的数据结构,用于存储和管理相关的数据。 using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Threading; 使用 Microsoft.Win32.SafeHandles 。 System.Runtime.InteropServices 被使用。 namespace AutoSwitchGUI { 通过这个类可以创建出相应的图形用户界面。 { [DllImport("kernel32.dll")] 公共静态外部方法 SafeWaitHandle 创建可等待定时器(IntPtr lpTimerAttributes,布尔值 bManualReset,字符串 lpTimerName); 在“kernel32.dll”中进行 DllImport 操作,并且设置了 SetLastError 为 true 。 使用 MarshalAs 特性并将其参数设置为 UnmanagedType.Bool 进行返回 公共静态外部方法 SetWaitableTimer 接受一个 SafeWaitHandle 类型的参数 hTimer,以及一个引用类型的 long 类型参数 pDueTime,一个 int 类型的参数 lPeriod,一个 IntPtr 类型的参数 pfnCompletionRoutine,一个 IntPtr 类型的参数 lpArgToCompletionRoutine 和一个 bool 类型的参数 fResume。该方法用于设置等待定时器。 [DllImport("kernel32.dll")] 公共静态外部函数 SetThreadExecutionState 接收一个 uint 类型的参数 esFlags 并返回一个 uint 值。 [DllImport("user32.dll")] 公共静态外部方法 mouse_event,它接受一个 32 位整数 dwFlags,一个 32 位整数 dx,一个 32 位整数 dy,一个 32 位整数 dwData,以及一个无符号指针 dwExtraInfo 作为参数。 公共事件 EventHandler 被引发唤醒; 创建了一个私有类型的 BackgroundWorker 对象,名为 bgWorker 。 公共结构体 auto_switch_gui_status_t { public bool test_status; public UInt64 test_times_cnt; public UInt64 test_times; public byte cur_state; public int s0_duration; public int s3_duration; } 公共的自动切换图形用户界面状态类型 auto_switch_gui_status_t 为 auto_switch_status ; public AutoSwitchGUI() { InitializeComponent(); bgWorker 的 DoWork 事件添加了一个事件处理程序,该处理程序为 bgWorker_Dowork 方法。 bgWorker 的 RunWorkerCompleted 事件被添加了一个新的事件处理程序,该处理程序为 bgWorker_RunWorkerCompleted 。 } 在 bgWorker 的 DoWork 事件中,当接收到 DoWorkEventArgs e 时,会执行以下操作:在私有方法内部进行相关处理。 { long waketime 等于 (long)e.Argument ; 使用 (SafeWaitHandle handle = CreateWaitableTimer(IntPtr.Zero, true, 这个GetType().Assembly.GetName().Name.ToString() + "Timer")) { 如果设置可等待定时器(handle),将唤醒时间(ref waketime)设置为 0,并且设置为非零值(IntPtr.Zero),设置为非零值(IntPtr.Zero),设置为真(true),那么就会成功设置可等待定时器。 { 使用一个 EventWaitHandle 对象 wh,将其初始化为 false 状态,并且设置为自动重置模式,即 EventResetMode.AutoReset { wh.SafeWaitHandle = handle; wh.WaitOne(); } } else { 使用 Marshal.GetLastWin32Error() 获取的最后一个 Windows 32 错误码,并抛出一个新的 Win32Exception 异常。 } } } 当 private 方法被触发时,它会接收到两个参数,分别是 sender 和 RunWorkerCompletedEventArgs e,这个方法用于处理后台工作线程完成后的相关操作。 { 调用 mouse_event 函数,其参数为 0x0001,0,1,0,UIntPtr.Zero 。 调用 mouse_event 函数,参数为 0x0001、0、-1、0 和 UIntPtr.Zero 。 auto_switch_status 的 test_times_cnt 加 1 ; TestTimes.Text 等于 auto_switch_status.test_times_cnt 转换为字符串后的结果。 SystemTimer 的 Interval 等于 auto_switch_status 的 s0_duration 乘以 1000 。 SystemTimer.Start(); } 公共方法用于设置唤醒时间,该时间以 UInt64 类型的数值表示。 { bgWorker 运行工作异步操作,操作的参数是当前时间(System.DateTime.Now)加上指定的秒数(time)后转换为文件时间(ToFileTime())。 } 在点击开始按钮时,会触发这个私有方法。这个方法接收两个参数,一个是发送者对象 sender,另一个是事件参数 EventArgs e。 { try { auto_switch_status 的 test_times 等于将 SetTestTimes.Text 转换为 UInt64 类型 auto_switch_status 的 s0_duration 等于将 S0Duration.Text 转换为整数类型 auto_switch_status 的 s3_duration 等于将 S3Duration.Text 转换为整数类型。 如果 auto_switch_status 的 test_times 大于 0 {SetThreadExecutionState 会设置一些特定的状态,包括 0x00000001 这个状态,也包括 0x00000002 这个状态,还包括 0x80000000 这个状态,同时也包括 0x00000040 这个状态。 TestStatus 的背景颜色被设置为绿色。 auto_switch_status 的 test_status 等于 true。 TestTimes.Text = "0"; auto_switch_status 的 test_times_cnt 等于 0 。 SystemTimer 的 Interval 等于 auto_switch_status 的 s0_duration 乘以 1000 。 auto_switch_status 的当前状态为 0。 SystemTimer.Start(); return; } } catch { } 显示一个消息框,内容为“Configuration Failed!”。 } 在 StopButton 被点击时(对象为 sender,事件为 e),会执行这个私有方法。 { SystemTimer.Stop(); auto_switch_status 的 test_status 等于 true。 TestStatus 的背景颜色被设置为红色。 } 在 SystemTimer 的 Tick 事件中,当触发该事件时,会调用这个私有方法,参数分别是 sender 和 e 。 { 如果 auto_switch_status 的当前状态为 0 { auto_switch_status 的当前状态为 0。 SystemTimer.Stop(); 如果 auto_switch_status 的 test_times_cnt 大于或等于 auto_switch_status 的 test_times { } else { 设置唤醒时间为 (UInt64)auto_switch_status.s3_duration ; Application 使系统进入挂起状态,挂起状态为 PowerState.Suspend,并且不强制关闭程序,也不保存程序状态。 Application 使系统进入休眠状态(PowerState.Hibernate),并且设置为不强制关闭应用程序,也不关闭系统电源。 } } 如果 auto_switch_status 的当前状态等于 1 { auto_switch_status 的 test_times_cnt 加 1 ; TestTimes.Text 等于 auto_switch_status.test_times_cnt 转换后的字符串形式。 auto_switch_status.cur_state = 0; SendKeys.Send(" "); 将 "TEST1\r\n" 添加到了 MessageInfo 的 Text 中 } } } } </code></pre></p>
另外声明,关于和我是参考如下链接的:
希望能帮到大家,此代码在我自己的笔记本上可以适用,在客户的笔记本上也可以适用。
# 如何搭建程序复现笔记本芯片在电源状态切换中的死锁问题
# 设置为
# 鼠标
# 自己的
# 转换为
# 死锁
# 挂起
# 第二个
# 就会
# 也不
# 比较容易
# 在我
# 第一个
# 不太
# 将其
# 时间为
# 一个问题
# 压力测试
# 第三个
# 切换到
# 过程中
# 杨凌买菜网站建设
# 营销推广对比图表怎么做
# 申请推广营销涨粉
# 酒店网站建设的公司
# 鸠江区招商局网站建设
# 临安seo网站推广
# 南宁网络seo优化
# 大冶关键词排名查询工具
# 加强公安网站建设的意义
# 营销推广渠道销售的区别
# 长春网站建设教案
# 浙江设计网站建设
# 孝感网站建设与推广论文
# 肥城网站建设渠道
# 南宁专业seo优化
# 龙溪机械网站建设费用
# 网站建设推广哪里好做点
# 谷歌seo收费书籍
# 网络seo案例
# 保定需要网站建设的企业
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
网络优化76771 】
【
技术知识130152 】
【
IDC云计算60162 】
【
营销推广131313 】
【
AI优化88182 】
【
百度推广37138 】
【
网站推荐60173 】
【
精选阅读31334 】
相关推荐:
app推广最实用的13个手段和渠道,抓紧收藏!
全球市场:SEO海外推广策略助力企业走向国际,重庆通用营销推广方案
app推广拉新这通过这4个市场推广策略来实现用户的拉新和流量暴涨!
如何快速提升app推广注册量,吸引大量粉丝关注?
入门SEO:打造属于你的网站流量帝国,沧州设计行业网站建设
关键字罗列-提升搜索引擎优化的秘密武器,十堰全网推广网站有哪些
超实用的手机APP试玩赚钱项目玩法分享!
揭秘引流项目之百度贴吧诱导引流项目的玩法和思路!
网赚小白们必看的广告联盟赚钱思路!
SEO有话:如何用精准优化助力企业在线增长,秦皇岛营销网站推广介绍
优化网站的秘诀:提高网站速度与用户体验,助力业务腾飞,seo韩语中文是什么
SEO就是:让你的品牌脱颖而出,获得更多曝光与流量,凤岗企业网站推广价格
目前APP引流最常见的四大推广方式就是他们了!
详细分析教大家怎么做APP地推拉新推广!
在微信公众号上投放cpc广告需要注意的几点问题,否则赔了夫人又折兵!
如何做好微信营销?只需要做好这几步就可以了!
为什么“蜘蛛弛查询”能成为提升网站排名的秘密武器?,无锡荣巷街道网站建设
SEO妍:搜索引擎优化的艺术,轻松打造网络营销新未来,绥德抖音seo优化
SEO查:如何用精准的SEO诊断助力网站流量爆发,鹤壁网站推广哪家有实力
网络兼职靠谱吗?正规的网络兼职赚钱渠道有哪些?
SEO拓客,让您的业务飞速增长!,江宁网站建设银行工作
网上多数的赚钱信息都是“搞信息差”,这才是网赚的精髓!
做国外广告联盟赚钱需要准备什么软件和注意哪些细节?
哪类的产品广告适合广告模式来进行推广?
6个快速有效的app推广渠道,轻松推广你的app!
为什么选择老域名注册,打造品牌价值的秘密武器,推广亲子鉴定网站
全网爬行:数据时代的隐秘力量,紫金网站制作推广运营
内容润色-提升文本质量,让您的文章更具吸引力,安岳营销短视频搜索推广
最详细的十个网站营销策略!以后再也不用担心网站的流量啦!
SOE优化:让你的网站轻松登顶,流量激增的秘密武器,茶陵网络营销推广方式
将网站封装成APP利用广告赚钱的操作思路玩法!
伪免费时代:真正的“免费”背后隐藏的秘密,会计考试网站建设
广告投放的渠道和方法有哪些?各自的优势在哪?
SEO查:如何通过精准优化让网站流量飞速增长,蔚来一年的营销推广费
网站上挂的广告联盟平台上的联盟广告不赚钱怎么办?
网赚游戏未来将进入3.0时代,想要赚钱的抓紧了!
SEO添加:提升网站流量与排名的必备策略,小企业seo实战技巧
了解SEO:让你的网站在搜索引擎中脱颖而出的秘密武器,何谓网站推广
互联网资源的无限潜力:如何利用数字世界为个人和企业创造价值,抖音seo公司收费
微信朋友圈广告的主要推广方法有哪些?
从“官网扒下来”看企业数字化转型的未来,建材行业全网推广营销
如何推动秀场|直播|快速发展?游戏运营思维值得借鉴!
做网赚想要月入过万所必须要经历的四个阶段!
国外广告联盟是怎么赚钱的?看完这几个案例收入吓你一跳!
全文缩写-提高效率,释放更多可能,设计类网站建设
个人站长通过网站营销快速获取大量流量的10个方法!
为什么选择老域名工具?提升网站SEO与品牌影响力的秘密武器,饰品店营销推广策略研究
SEO但是,这些常见误区你真的知道吗?,温州品牌营销推广价格
“多网建站”助力企业跨越发展,开启全新数字化时代,常州产品seo优化
SEO已经成为数字营销的核心,如何利用SEO提升网站流量和转化率,镇江网站建设方案及报价
2026-01-18
致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。