I want to turn off the hard disk through program.
Reference to the SetPowerState function of WMI CIM_DiskDrive Class and the following URL
http://msdn.microsoft.com/en-us/library/aa390421(VS.85).aspx ,
I write a VC6 programe,but encountered problem.
1.Can SetPowerState really realize turn off the hard disk?
Platform SDK says "Defines the desired power state for a logical device
and when a device should be put into that state. Not implemented by WMI."
What is "Not implemented by WMI" mean?
2.When called pClassInstance->Put(L"PowerState", ...),it failed,return value is "WBEM_E_TYPE_MISMATCH",but refer to Platform SDK,datatype of "PowerState" is VT_UI2.
I'm puzzled.
3. If SetPowerState can realize turn off the hard disk,
how can I realize control a single disk if I have two or more disk in my system?
// Create the values for the in parameters
VARIANT varPowerState;
varPowerState.vt = VT_UI2;
varPowerState.uiVal = 6;
// Store the value for the in parameters
hres = pClassInstance->Put(L"PowerState", 0,&varPowerState, 0);
VARIANT varDate;
varDate.vt = VT_DATE ;
varDate.uiVal = 0;
// Store the value for the in parameters
hres = pClassInstance->Put(L"Time", 0,&varDate, 0);
>> 1.Can SetPowerState really realize turn off the hard disk?
Probably not. Unless you have a custom provider intalled...
http://msdn.microsoft.com/en-us/library/aa393485(VS.85).aspx
This method is currently not implemented by WMI. To use this method, you must implement it in your own provider.
>> 2. ... it failed, ... I'm puzzled
It's probably because WMI does not "implement" CIM_DiskDrive. You should be using the Win32_* derived classes instead. In this case, Win32_DiskDrive.
>> 3. ... how can I realize control a single disk if I have two or more disk in my system?
The example code you linked to used Win32_Process.Create(). This method does not require an "instance" of a Win32_Process. In other words, you don't need a Win32_Process object that represents a currently running process in order to call the Create() method. If you were to call Win32_Process.Terminate(), then the object would need to be a real instance (representing a real process).
The first parameter to ExecMethod() takes an object path. Here is where you specify an object instance using the "key" object property to uniquely identify it.
http://msdn.microsoft.com/en-us/library/aa390350(VS.85).aspx
A typical way of doing this is to SELECT the current instances in the system, then get the "__Path" property to get the full pathname of the object instance.
gg
Zhoucj
October 25th, 2008, 04:55 AM
Thank you,Codeplug.
Please see bellow.
>>Probably not. Unless you have a custom provider intalled...
This mean that I must define the SetPowerState function myself?
Well,how can I do this,can you show me a sample or URL link?
>> You should be using the Win32_* derived classes instead. In this case, Win32_DiskDrive.
I used Win32_DiskDrive instead, but result is the same,"WBEM_E_TYPE_MISMATCH".
>> A typical way of doing this is to SELECT the current instances in the system, then get the "__Path" property to get the full pathname of the object instance.
I noticed that for CIM_DiskDrive or Win32_DiskDrive class,"DeviceID" is the "key" object property.
So if I have two disks in my system,after select,I can get DeviceID such as
"\\.\PHYSICALDRIVE0" and "\\.\PHYSICALDRIVE0".
If I want to turn off the first disk,
then how can I use "\\.\PHYSICALDRIVE0" to generate the first parameter to ExecMethod()?
Could you give me a detail?Thank you.
Codeplug
October 25th, 2008, 10:21 AM
Forget about WMI - it won't do what you want.
The best you can do is change the power policy for when disks should spin-down.
//------------------------------------------------------------------------------
// Check admin limits for spindown settings - you must have sufficient
// privileges in order to change these settings
LONG EnsureSpindownWithinAdminPolicy(ULONG timeoutSecs)
{
ADMINISTRATOR_POWER_POLICY app;
LONG status = GetPowerInformation(AdministratorPowerPolicy, &app);
if (status != STATUS_SUCCESS)
return status;
//------------------------------------------------------------------------------
// Get the information you see in the Control Panel "Power Options" applet.
LONG PwMgmt_GetCurrentPowerPolicy(POWER_POLICY &pp)
{
UINT scheme;
if (!GetActivePwrScheme(&scheme))
{
DWORD le = GetLastError();
if (!le)
return ERROR_UNHANDLED_ERROR;
return le;
}//if
if (!ReadPwrScheme(scheme, &pp))
{
DWORD le = GetLastError();
if (!le)
return ERROR_UNHANDLED_ERROR;
return le;
}//if
//------------------------------------------------------------------------------
// Permanently set spindown timeout for current power scheme
// NOTE: Does not affect laptops on DC (battery) power
LONG PwMgmt_SetSpindownTimeoutPerm(ULONG timeoutSecs)
{
// ensure the timeout is within the admin policy range
LONG status = EnsureSpindownWithinAdminPolicy(timeoutSecs);
if (status != STATUS_SUCCESS)
return status;
UINT scheme;
if (!GetActivePwrScheme(&scheme))
{
DWORD le = GetLastError();
if (!le)
return ERROR_UNHANDLED_ERROR;
return le;
}//if
POWER_POLICY pp;
if (!ReadPwrScheme(scheme, &pp))
{
DWORD le = GetLastError();
if (!le)
return ERROR_UNHANDLED_ERROR;
return le;
}//if
pp.user.SpindownTimeoutAc = timeoutSecs;
if (!SetActivePwrScheme(scheme, 0, &pp))
{
DWORD le = GetLastError();
if (!le)
return ERROR_UNHANDLED_ERROR;
return le;
}//if
return 0;
}//PwMgmt_SetSpindownTimeoutPerm
//------------------------------------------------------------------------------
// Temporarily set spindown timeout for current power scheme
// NOTE: If you look at it in control panel, it will become permanent, even if
// you hit cancel. Otherwise original settings will revert after a reboot.
// NOTE: Does not affect laptops on DC (battery) power
LONG PwMgmt_SetSpindownTimeoutTemp(ULONG timeoutSecs)
{
// ensure the timeout is within the admin policy range
LONG status = EnsureSpindownWithinAdminPolicy(timeoutSecs);
if (status != STATUS_SUCCESS)
return status;
SYSTEM_POWER_POLICY spp;
status = GetPowerInformation(SystemPowerPolicyAc, &spp);
if (status != STATUS_SUCCESS)
return status;
spp.SpindownTimeout = timeoutSecs;
status = SetPowerInformation(SystemPowerPolicyAc, &spp);
status = PwMgmt_SetSpindownTimeoutPerm(newSpindown);
//status = PwMgmt_SetSpindownTimeoutTemp(newSpindown);
if (status != STATUS_SUCCESS)
{
cerr << "Failed to set SpindownTimeoutAc to " << newSpindown
<< ", " << status << endl;
return status;
}//if
cout << "Set SpindownTimeoutAc to " << newSpindown << endl;
return 0;
}//maingg
Laurentis
October 26th, 2008, 05:18 AM
Forget about WMI - it won't do what you want.
The best you can do is change the power policy for when disks should spin-down.
No.
The 2 right methods are WMI and an undocumented api call
Never change GPP, it's a global parameter
Codeplug
October 26th, 2008, 08:27 AM
>> No. The 2 right methods are WMI and an undocumented api call
Are you keeping it a secret? Care to share some actual information with us?
gg
Codeplug
October 26th, 2008, 09:10 AM
So you can send ATA commands directly to a drive using IOCTL_ATA_PASS_THROUGH for XP SP2 or higher. Prior to that, you use the undocumented IOCTL_IDE_PASS_THROUGH. This would allow you to spindown a specific drive without affecting other drives.
There's a Win32 version of the Linux hdparm utility which can spin down an individual drive. You could call this utility directly or try to incorporate its source into your own:
http://hdparm-win32.dyndns.org/hdparm/
WMI still isn't an option.
gg
Zhoucj
October 27th, 2008, 07:52 AM
>>The best you can do is change the power policy for when disks should spin-down.
Thank you.I tried this, and saw that this have the same result as I changed the "turn off disk time" in "control pannel->power option".
But this still have defect:
There are two disks in my system,I just want to realize turn off the disk that system Volume not exist in.In this way,two disks sleeped when the system idled for a time setted,and then if I access the system disk,another
disk get run together[I wanted the other disk sleeped until actualy access it].
Can I realize this in the way you offered?
Zhoucj
October 27th, 2008, 07:53 AM
>>So you can send ATA commands directly to a drive using IOCTL_ATA_PASS_THROUGH for XP SP2 or higher...
I will try this way, thank you very much..
Zhoucj
October 27th, 2008, 11:35 PM
>>So you can send ATA commands directly to a drive using IOCTL_ATA_PASS_THROUGH for XP SP2 or higher...
ATA/ATAPI-6 Spec specificationSpec shows that SLEEP command can cause the device to enter Sleep
mode.I try to use it,but encounter problem:
Call the function "DeviceIoControl" failed,and GetLastError returns error code
is "122".
I tried to use IOCTL_ATA_PASS_THROUGH instead of DFP_SEND_DRIVE_CMD,still failed,and GetLastError returns error code
is "87".
DFP_SEND_DRIVE_COMMAND is not right?Or SENDCMDINPARAMS,SENDCMDOUTPARAMS
[these two structure in reference to one SMART program from
http://smartlinux.sourceforge.net/smart/index.php] is not correct?
Or others?
Any advice would be appreciated,thanks.
typedef struct _IDEREGS {
BYTE bFeaturesReg; // Used for specifying SMART "commands".
BYTE bSectorCountReg; // IDE sector count register
BYTE bSectorNumberReg; // IDE sector number register
BYTE bCylLowReg; // IDE low order cylinder value
BYTE bCylHighReg; // IDE high order cylinder value
BYTE bDriveHeadReg; // IDE drive/head register
BYTE bCommandReg; // Actual IDE command.
BYTE bReserved; // reserved for future use. Must be zero.
} IDEREGS, *PIDEREGS, *LPIDEREGS;
typedef struct _SENDCMDINPARAMS {
DWORD cBufferSize; // Buffer size in bytes
IDEREGS irDriveRegs; // Structure with drive register values.
BYTE bDriveNumber; // Physical drive number to send
// command to (0,1,2,3).
BYTE bReserved[3]; // Reserved for future expansion.
DWORD dwReserved[4]; // For future use.
BYTE bBuffer[1]; // Input buffer.
} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
typedef struct _SENDCMDOUTPARAMS {
DWORD cBufferSize; // Size of bBuffer in bytes
DRIVERSTATUS DriverStatus; // Driver status structure.
BYTE bBuffer[1]; // Buffer of arbitrary length in which to store
// the data read from the drive.
} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
found this old thread while searching for the same problem. Did you have any success issuing the sleep command?
Regards,
Christian.
JohnCz
September 27th, 2011, 03:15 PM
Platform SDK says "Defines the desired power state for a logical device
and when a device should be put into that state. Not implemented by WMI."
What is "Not implemented by WMI" mean?......
It means exactly what it says.
This method is currently not implemented by WMI. To use this method, you must implement it in your own provider.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.