Fall is officially in full swing on the West Coast - seriously, look at this weather.
It’s the perfect time to drink coffee, sit inside, and code. There was just one problem with that for me - I actually need to step away from my machine from time to time to brew some coffee, and while I was gone, the computer would go to sleep, and I needed to wake it up, enter my credentials. Wasting precious 3 seconds, every hour or so. Because I am at home, I am not worried about some malicious actor snooping over my desktop and the open browser tabs (most open to “how to write output powershell” or some variation of queries that kick the impostor syndrome in full gear).
On macOS, there is a very helpful command for this very purpose -
caffeinate -d. Windows has nothing like that out of the box, but that doesn’t mean I can’t hack something together that gets the job done with PowerShell. There are some scripts in the wild that try to press the Scroll Lock button virtually, but I don’t consider that to be an elegant solution. There has to be a better way.
Lucky for us, there is an API that Windows has, called
SetThreadExecutionState1, that can be used for the purpose of this project. This is the same API that is used by media players, for example, when they need to keep the screens on whenever a movie is playing on your computer. We can re-purpose it to be our Windows caffeination tool.
Let’s get to the script first - you can use it right away:
First, if you are at least somewhat familiar with P/Invoke, I am re-creating the managed signature for the native Windows API. Then, following the guidelines in the documentation for
SetThreadExecutionState, I am defining the unsigned integer values for the two flags that we need to pass to the API. There is also a job name defined, and you might be wondering why I need it.
Well, as it turns out, calling
Add-Type2 in the same PowerShell session can lead you to an error, that stems from how .NET CLR handles types within the current application context. So, what I end up doing is creating background jobs, that run within their own, dedicated context, that allows me to use the
Add-Type cmdlet without any blockers. To start the job, I rely on standard PowerShell tools to handle background execution3. Inside the background job, I am calling the API as if I am an application that needs to have the display on.
When I terminate the script with
Ctrl+C, the job is stopped and removed - that’s it! Now I can make my computer be awake just like I could on macOS. To run the script, you can save it locally, and run:
Have any thoughts? Let me know on Twitter!