9

My program performs a task on the hard disk free space. The task is quite long, it takes 1-2 hours.

The problem is that on laptop the hard disk may be turned off after few minutes when the user is inactive.

How do I programmatically prevent Windows from hard disk spin down (power off) ?

TLama
  • 75,147
  • 17
  • 214
  • 392
user382591
  • 1,320
  • 5
  • 19
  • 39
  • 4
    Set a different power plan from control panel manually. I would delete a program that changes power plan behind my back. – kludg Jan 04 '12 at 20:27
  • 10
    The computer powers down the disk whilst it is in use? That doesn't really sound right to me. Are you sure? – David Heffernan Jan 04 '12 at 21:03
  • In short, windows will not power off the disk during an active disk write, but the OP is not doing a proper file-read or file-write, and so Windows may suspend the disk, or the entire computer. The OP may be slightly mis-stating the problem. – Warren P Jan 04 '12 at 21:29
  • 1
    This isn't "programmatic" but you could always consider turning drive indexing on. >.< It NEVER stops, then... – Tass Jan 04 '12 at 21:37
  • 1
    Windows will not turn HDD off while it is active. And Windows will turn HDD on when software requests disk operation. Solved, no? – OnTheFly Jan 04 '12 at 23:23
  • 1
    @user539484, ehm, what if... you have HDD spin down time set to 2 minutes and you are performing some operation in memory e.g. 20 minutes and each 2.5 minutes you need to read some data from the disk. It takes some time until the disk is ready from the "sleep" mode. I know the question doesn't make sense as it's stated but it's interesting. Anyway there is the [`SetThreadExecutionState`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa373208%28v=vs.85%29.aspx) function which can prevent system from idle mode, but I'm not sure yet if this applies also to disk drives. – TLama Jan 04 '12 at 23:49
  • @TLama, well, assuming its perfectionist me - data read period is optimal already :-) So there will be choice to lose battery time in favour of speed, or vice versa. – OnTheFly Jan 05 '12 at 00:28
  • 4
    I'm still struggling to understand why an app that performs some operation that can take from 1 to 2 hours would be bothered by a 10 sec spinup time. Why worry? – Martin James Jan 05 '12 at 01:07
  • 3
    @MartinJames, OK, let's say you have the operation which takes 2 hours and which have to read data from disk each 2.5 minutes. This will resume the disk 48 times and it will take additional 8 minutes to that operation if the spin up time will take 10 seconds as you said. And those files cannot be loaded into memory before they are very big and depends on the result of the calculations. I'm just taking this question as it is ;) – TLama Jan 05 '12 at 08:33
  • @TLama - OK, I've got it. In that case, I would try to spin the disk up 'early', (create temporary file?), though I accept that this is difficult to do across multiple machines with different performance and different loading. Myybe some sort of heuristic timer that adjusts its interval depending on how long each disk write takes? – Martin James Jan 05 '12 at 11:07
  • @Martin, I believe there are functions for extending the disk spin down timer period. I would try the `SetThreadExecutionState` but I can't verify if it relates also to disk drive because I've no machine which would ever shut down disk :( At least this function can be used (and not to be called periodically) to keep the display on. – TLama Jan 05 '12 at 11:36

2 Answers2

10

To prevent the system from entering idle mode you may try to use the SetThreadExecutionState function. This function informs the system that the application is in use and allows you to specify the thread's execution requirements. The usage can be like this, but I'm not sure if this affects also the disk power down timer:

type
  EXECUTION_STATE = DWORD;

const
  ES_SYSTEM_REQUIRED = $00000001;
  ES_DISPLAY_REQUIRED = $00000002;
  ES_USER_PRESENT = $00000004;
  ES_AWAYMODE_REQUIRED = $00000040;
  ES_CONTINUOUS = $80000000;

function SetThreadExecutionState(esFlags: EXECUTION_STATE): EXECUTION_STATE;
  stdcall; external 'kernel32.dll' name 'SetThreadExecutionState';

procedure TForm1.Button1Click(Sender: TObject);
begin
  if SetThreadExecutionState(ES_CONTINUOUS or ES_SYSTEM_REQUIRED or
    ES_AWAYMODE_REQUIRED) <> 0 then
  try
    // execute your long running task here
  finally
    SetThreadExecutionState(ES_CONTINUOUS);
  end;
end;

Or there is also available the new set of functions PowerCreateRequest, PowerSetRequest and PowerClearRequest designed for Windows 7, but the documentation is confusing and I haven't found any example of their usage at this time.

Or you can modify the power settings by PowerWriteACValueIndex or PowerWriteDCValueIndex functions with the GUID_DISK_SUBGROUP subgroup of power settings.

Victoria
  • 7,822
  • 2
  • 21
  • 44
TLama
  • 75,147
  • 17
  • 214
  • 392
  • You're welcome. Anyway what have you used, the code example from the post ? Does it mean that `SetThreadExecutionState` affects also resetting the disk power down timer ? The MSDN documentation is quite weak (and I would like to delete the note about _untested_), that's why I'm asking :) Thanks – TLama Jan 05 '12 at 21:10
  • 1
    I tested it. That works like a charm... SetThreadExecutionState affects also resetting of the disk power down timer. – user382591 Jan 06 '12 at 07:10
5

Windows does not allow applications to disable power control changes, because buggy applications were causing batteries to be drained. See http://blogs.msdn.com/oldnewthing/archive/2007/04/16/2148139.aspx

You can get notified when the system power status is about to be changed. See WM_POWERBROADCAST Messages.

mirh
  • 514
  • 8
  • 14
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • 1
    But you may tell the system you need an extra time for your task (e.g. when you are watching the movie you have to tell the system you don't want to turn off the display), and IMHO that's what is (as TLama said in his comment) the function `SetThreadExecutionState` for. So in fact you are breaking the power plan. – Martin Reiner Jan 05 '12 at 00:24
  • @Martin, as you mentioned watching the movie you may use the [`SetThreadExecutionState`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa373208%28v=vs.85%29.aspx) with `ES_DISPLAY_REQUIRED` flag to keep your display on. The problem is that I'm not sure (and don't have a testing machine) if this function is applicable also for disk idle timer. – TLama Jan 05 '12 at 00:56