关于通过CMD命令睡眠Windows10的研究

网络上能找到的睡眠命令几乎都使用的rundll32.exe​来实现,然而经过检索发现,这似乎是不正确的,这种方法下实现的是休眠(hibernate)而不是睡眠(suspend)。

主流的实现方式:​rundll32.exe powrprof.dll,SetSuspendState 0,1,0

下面我们分析一下,首先看SetSuspendState​的 函数签名

可以看到MSDN中提到,如果第一个参数为True,则系统会休眠,False则系统会睡眠

看到这里,仿佛该方法是正确的,因为其看起来是分别把0,1,0传入了方法的三个参数,0代表第一个参数是False,然而实际上,rundll32不是这样传参的,这种用法是对rundll32的错误使用。

为什么说这种用法是对rundll32的错误使用呢?根据 How to use Rundll32 to execute DLL Function? - Stack Overflow ,rundll32仅支持签名为void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);​的函数,因此0,1,0​并不会按照你预想的方式挨个传递进去。相反,在这种运行方式下,SetSuspendState​函数实际接收到的参数是:[SomePtr1], [SomePtr2], "0,1,0", ...​,这就导致了第一个参数一定不为0,也就是一定为True,也就是实际会使得系统休眠而不是睡眠。

那么为什么网络上有很多人反馈这个命令好使呢?这里猜测是因为他们把休眠功能关掉了(powercfg -hibernate off​或者控制面板手动关掉)

正确方式

分析完了主流方法为什么是错误的,我们来谈一下如何正确的通过CMD睡眠系统呢?这里的核心思路还是调用SetSuspendState​这个函数

  1. 自己写一个ahk或者C#或者C++小程序,通过DllCall之类的技术正确的调用SetSuspendState​来实现睡眠。这种方法的缺点是需要一个单独的程序。
  2. 通过powershell来调用Winform中的SetSuspendState​函数:powershell "[Void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');[System.Windows.Forms.Application]::SetSuspendState('Suspend', $false, $false);"

感想

有时候互联网上方法也不是那么可信,还是要自己去探究各中原理😝