Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Temporarily disable CD/DVD drive to prevent spinning-up...?



  • Please log in to reply
19 replies to this topic
chaz
  • Members
  • 192 posts
  • Last active: Oct 01 2015 02:42 AM
  • Joined: 26 Mar 2013

Does anybody know of any way to temporarily disable the CD/DVD drive on a laptop to prevent it from spinning up? I want to do this because I want to store a DVD+RW in the drive and use it for periodic backups, but right now every time I unlock the computer or open Explorer the disk drive will spin-up and it's really loud and disruptive. I've tried to stick a post-it note over the lens, and this stops it from continually spinning, but it will still spin it to check if there's a disk (normally you can't hear this because there's no disk in the drive to make noise).

 

Optimally, I'd like to be able to assign it to a hotkey so I can easily enable or disable it.

 

Any thoughts?


Find me at the other forum as timeFlies.


Linear Spoon
  • Members
  • 842 posts
  • Last active: Sep 29 2015 03:56 AM
  • Joined: 29 Oct 2011
✓  Best Answer

This turned out more complicated than I thought it would. I have to go soon so this script isn't as polished as I would like but it's working.

 

Steps:

 

1. Open Device Manager (start search on windows 7 is an easy way to get to it)

2. Find the human friendly name of your CD drive

pQvJnDq.png

 For example mine is "MATSHITA BD-CMB UJ242AS"

3. Modify the script below setting DeviceName to the text you just found in device manager.

4. Run the script. Pressing F1 should enable the device while F2 disables it. If it doesn't work, try running the script with administrator privileges.

  Hint: Check the status in device manager. It will get a small arrow icon when disabled. (See image)

RBEIPac.png

 

One last note, it may not be possible to disable and/or enable the device without restarting the computer.

 

 

 

And the script:

;Important! Modify this variable with the name of the device to disable:
DeviceName := "MATSHITA BD-CMB UJ242AS"



;Adapted from:
;http://stackoverflow.com/questions/4097000/how-do-i-disable-a-system-device-programatically

hModule := DllCall("LoadLibrary", "str", "setupapi.dll")
OnExit, FreeLib

info := DllCall("setupapi.dll\SetupDiGetClassDevsW", "ptr", 0, "ptr", 0, "ptr", 0, "uint", DIGCF_ALLCLASSES := 4)

if (info = -1)
{
  Msgbox % "SetupDiGetClassDevs failed: " A_LastError
  Exitapp
}

DevInfo_Data(di)
Loop
{
  if !DllCall("setupapi.dll\SetupDiEnumDeviceInfo", "ptr", info, "uint", A_Index-1, "ptr", &di)
  {
    If (A_LastError = 259) ;ERROR_NO_MORE_ITEMS
    {
      Msgbox % "Could not find the device."
      Exitapp
    }
    else
    {
      Msgbox % "SetupDiEnumDeviceInfo failed: " A_LastError
      Exitapp
    }
  }

  if (GetDeviceString(info, di, 12) = DeviceName)
    break
}
return

F1::
  Traytip, Dev State Change, Enabling %DeviceName%
  MakeChange(info, di, 1)
return

F2::
  Traytip, Dev State Change, Disabling %DeviceName%
  MakeChange(info, di, 2)
return

Esc::ExitApp

FreeLib:
  DllCall("setupapi.dll\SetupDiDestroyDeviceInfoList", "ptr", info)
  DllCall("FreeLibrary", "Ptr", hModule)
  ExitApp
return 

PropChange_Params(byref pcp, InstallFunction, state)
{
  /*
  SP_CLASSINSTALL_HEADER
  sizeof: 8
  0 - cbSize
  4 - InstallFunction

  SP_PROPCHANGE_PARAMS
  sizeof: 20
  0 - Install header
  8 - StateChange
  12 - Scope
  16 - HwProfile
  */
  VarSetCapacity(pcp, 20)
  Numput(8, pcp, 0, "uint"), Numput(InstallFunction, pcp, 4, "uint")
  Numput(1, pcp, 12, "uint"), Numput(0, pcp, 16, "uint")

  ;DICS_ENABLE = 1
  ;DICS_DISABLE = 2
  Numput(state, pcp, 8, "uint")
}

GetDeviceString(info, byref di, propID = 1)
{
  ;http://msdn.microsoft.com/en-us/library/windows/hardware/ff551967(v=vs.85).aspx
  VarSetCapacity(buf, 512), VarSetCapacity(strsz, 4)
  r := DllCall("setupapi.dll\SetupDiGetDeviceRegistryPropertyW", "ptr", info, "ptr", &di
    , "uint", propID, "ptr", 0, "ptr", &buf, "uint", 512, "ptr", &strsz)
  if !r 
  {
    if (A_LastError = 13) ;ERROR_INVALID_DATA
      return ""
    Msgbox % "SetupDiGetDeviceRegistryProperty failed: " A_LastError
    ExitApp
  }
  return StrGet(&buf, NumGet(strsz, "uint"))  
}

MakeChange(info, byref di, newstate)
{
  PropChange_Params(pcp, 0x12, newstate)
  if !DllCall("setupapi.dll\SetupDiSetClassInstallParams", "ptr", info, "ptr", &di, "ptr", &pcp, "uint", 20)
  {
    Msgbox % "SetupDiSetClassInstallParams failed: " A_LastError
    Exitapp
  }

  if !DllCall("setupapi.dll\SetupDiChangeState", "ptr", info, "ptr", &di)
  {
    Msgbox % "SetupDiChangeState failed: " A_LastError
    Exitapp
  }
}

DevInfo_Data(byref di)
{
  /*
  SP_DEVINFO_DATA struct
  sizeof: 28
   0 - cbSize
   4 - ClassGuid
   20 - DevInst
   24 - reserved
  */
  VarSetCapacity(di, 24+A_PtrSize,0), Numput(24+A_PtrSize, di, 0, "uint")
}

Join us at the new forum - http://www.ahkscript.org/

 


chaz
  • Members
  • 192 posts
  • Last active: Oct 01 2015 02:42 AM
  • Joined: 26 Mar 2013

Looks good, but I can't try it because the  DevInfo_Data() function definition is not included in the script, and I was not able to find anything in a quick search of the forums.

 

 

One last note, it may not be possible to disable and/or enable the device without restarting the computer.

 

It appears that I might not need to reboot because when I disable the drive manually in Device Manager, it won't show up anymore in My Computer and my AHK Eject hotkey won't open it. However, if I push the physical button on the drive, it will open, but without the five second delay that normally exists, indicating that maybe the button will operate regardless if it is disabled, as long as it has power.

 

Thanks a lot! It looks like this might work and it sure will be useful if it does, but like I said before it won't work because of the missing function definition. I wouldn't have a clue as to where to start if I were to write this myself.


Find me at the other forum as timeFlies.


Eedis
  • Members
  • 1775 posts
  • Last active: Aug 14 2015 06:33 PM
  • Joined: 12 Jun 2009

Holy crap, thanks also Linear Spoon! I was wondering if this could be done too, just wasn't relevant enough for me to research it and happened to see this. :p


AutoHotkey state, the forum, Poly, and Drainx1. The short story.
I love my wife, my life, my atomic-match; for giving me the greatest gift a man could ask for, such a perfect and beautiful little girl.
9rjbjc.png

Linear Spoon
  • Members
  • 842 posts
  • Last active: Sep 29 2015 03:56 AM
  • Joined: 29 Oct 2011

Sorry I must not have selected it when I went to copy and paste the script. I've modified the script in my first post to include it.


Join us at the new forum - http://www.ahkscript.org/

 


chaz
  • Members
  • 192 posts
  • Last active: Oct 01 2015 02:42 AM
  • Joined: 26 Mar 2013

Great, it works! Though I noticed that if I wake my computer from sleep it'll start spinning up sometimes—probably specific to this device and not something that can be changed. My solution is just to re-disable it.

 

You should post this in the Scripts forum so more people see it.


Find me at the other forum as timeFlies.


DTOXX
  • Members
  • 7 posts
  • Last active: Apr 11 2014 05:34 PM
  • Joined: 01 Jun 2013

I've been searching for a script like this one for quite a while now. I'm experiencing a similar issue with my DVD drive being accessed on nearly every file operation - very annoying.

 

I have a problem running the script, though. I get this error: SetupDiEnumDeviceInfo failed: 1784

 

I double-checked to make sure the DeviceName is correct.



Linear Spoon
  • Members
  • 842 posts
  • Last active: Sep 29 2015 03:56 AM
  • Joined: 29 Oct 2011

1784 is ERROR_INVALID_USER_BUFFER. Sort of cryptic and unhelpful. 

 

Are you using Unicode AHK? If so, version and OS?

 

I tested on Unicode v1.1.10.01 with Windows 7.


Join us at the new forum - http://www.ahkscript.org/

 


DTOXX
  • Members
  • 7 posts
  • Last active: Apr 11 2014 05:34 PM
  • Joined: 01 Jun 2013

I believe that I installed the 64-bit Unicode version - v1.1.10.01 on Win7 Ultimate 64-bit, but I can't be completely sure - should I reinstall a different version?

 

-- UPDATE --

 

I reinstalled the 32-bit Unicode version and attempted to run the script. I'm not getting the error that I did before, but I'm getting a new error when using the F1/F2 hotkeys:

 

SetupDiChangeState failed: -536870389



Linear Spoon
  • Members
  • 842 posts
  • Last active: Sep 29 2015 03:56 AM
  • Joined: 29 Oct 2011

I found the cause of the original problem - 

If the cbSize member is not set correctly for an output parameter, the function will fail and set an error code of ERROR_INVALID_USER_BUFFER.

I've updated my original post to fix this issue.

 

As for your second error, I was getting something like that at first, but it stopped when I used LoadLibrary on setupapi.dll. That's not a Windows error code. Are you using the exact same script in my first post?


Join us at the new forum - http://www.ahkscript.org/

 


DTOXX
  • Members
  • 7 posts
  • Last active: Apr 11 2014 05:34 PM
  • Joined: 01 Jun 2013

OK, I reverted to the 64-bit Unicode version and confirmed that the original error no longer occurs. I hope that I'm using the correct script, though, since I'm still getting the second error. This is the script that I'm using:

;Important! Modify this variable with the name of the device to disable:
DeviceName := "MATSHITA BD-CMB UJ141AF"


;Adapted from:
;http://stackoverflow.com/questions/4097000/how-do-i-disable-a-system-device-programatically

hModule := DllCall("LoadLibrary", "str", "setupapi.dll")
OnExit, FreeLib

info := DllCall("setupapi.dll\SetupDiGetClassDevsW", "ptr", 0, "ptr", 0, "ptr", 0, "uint", DIGCF_ALLCLASSES := 4)

if (info = -1)
{
  Msgbox % "SetupDiGetClassDevs failed: " A_LastError
  Exitapp
}

DevInfo_Data(di)
Loop
{
  if !DllCall("setupapi.dll\SetupDiEnumDeviceInfo", "ptr", info, "uint", A_Index-1, "ptr", &di)
  {
    If (A_LastError = 259) ;ERROR_NO_MORE_ITEMS
    {
      Msgbox % "Could not find the device."
      Exitapp
    }
    else
    {
      Msgbox % "SetupDiEnumDeviceInfo failed: " A_LastError
      Exitapp
    }
  }

  if (GetDeviceString(info, di, 12) = DeviceName)
    break
}
return

F1::
  Traytip, Dev State Change, Enabling %DeviceName%
  MakeChange(info, di, 1)
return

F2::
  Traytip, Dev State Change, Disabling %DeviceName%
  MakeChange(info, di, 2)
return

Esc::ExitApp

FreeLib:
  DllCall("setupapi.dll\SetupDiDestroyDeviceInfoList", "ptr", info)
  DllCall("FreeLibrary", "Ptr", hModule)
  ExitApp
return 

PropChange_Params(byref pcp, InstallFunction, state)
{
  /*
  SP_CLASSINSTALL_HEADER
  sizeof: 8
  0 - cbSize
  4 - InstallFunction

  SP_PROPCHANGE_PARAMS
  sizeof: 20
  0 - Install header
  8 - StateChange
  12 - Scope
  16 - HwProfile
  */
  VarSetCapacity(pcp, 20)
  Numput(8, pcp, 0, "uint"), Numput(InstallFunction, pcp, 4, "uint")
  Numput(1, pcp, 12, "uint"), Numput(0, pcp, 16, "uint")

  ;DICS_ENABLE = 1
  ;DICS_DISABLE = 2
  Numput(state, pcp, 8, "uint")
}

GetDeviceString(info, byref di, propID = 1)
{
  ;http://msdn.microsoft.com/en-us/library/windows/hardware/ff551967(v=vs.85).aspx
  VarSetCapacity(buf, 512), VarSetCapacity(strsz, 4)
  r := DllCall("setupapi.dll\SetupDiGetDeviceRegistryPropertyW", "ptr", info, "ptr", &di
    , "uint", propID, "ptr", 0, "ptr", &buf, "uint", 512, "ptr", &strsz)
  if !r 
  {
    if (A_LastError = 13) ;ERROR_INVALID_DATA
      return ""
    Msgbox % "SetupDiGetDeviceRegistryProperty failed: " A_LastError
    ExitApp
  }
  return StrGet(&buf, NumGet(strsz, "uint"))  
}

MakeChange(info, byref di, newstate)
{
  PropChange_Params(pcp, 0x12, newstate)
  if !DllCall("setupapi.dll\SetupDiSetClassInstallParams", "ptr", info, "ptr", &di, "ptr", &pcp, "uint", 20)
  {
    Msgbox % "SetupDiSetClassInstallParams failed: " A_LastError
    Exitapp
  }

  if !DllCall("setupapi.dll\SetupDiChangeState", "ptr", info, "ptr", &di)
  {
    Msgbox % "SetupDiChangeState failed: " A_LastError
    Exitapp
  }
}

DevInfo_Data(byref di)
{
  /*
  SP_DEVINFO_DATA struct
  sizeof: 28
   0 - cbSize
   4 - ClassGuid
   20 - DevInst
   24 - reserved
  */
  VarSetCapacity(di, 24+A_PtrSize,0), Numput(24+A_PtrSize, di, 0, "uint")
}


Linear Spoon
  • Members
  • 842 posts
  • Last active: Sep 29 2015 03:56 AM
  • Joined: 29 Oct 2011

Try adding this after line 8 and let me know what it says:

Msgbox % hModule

The LoadLibrary call is the only thing that isn't error checked. hModule should be nonzero if it succeeds. 


Join us at the new forum - http://www.ahkscript.org/

 


DTOXX
  • Members
  • 7 posts
  • Last active: Apr 11 2014 05:34 PM
  • Joined: 01 Jun 2013

I added the code and the result is:

 

-40697856



Linear Spoon
  • Members
  • 842 posts
  • Last active: Sep 29 2015 03:56 AM
  • Joined: 29 Oct 2011

The only idea I have now is that the device you've selected can't be disabled without a reboot. I will research more into it later tonight.


Join us at the new forum - http://www.ahkscript.org/

 


Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

Though I noticed that if I wake my computer from sleep it'll start spinning up sometimes—probably specific to this device and not something that can be changed. My solution is just to re-disable it.

 

Some devices initialize as soon as they have power, even without any physical connection to a motherboard.  I found that using Nero DriveSpeed, my DVD drive would always spin up to full speed when waking, then promptly slow down to almost silent.  My solution was to take the disc out of the drive...