sb1920alk Posted January 27, 2010 Share Posted January 27, 2010 I'm using WinPE 3.0. This script opens the CD tray fine in XP, but not in WinPE. Any ideas or can someone confirm that it is not possible? Thanks $var = DriveGetDrive( "CDROM" ) If NOT @error Then For $i = 1 to $var[0] CDTray($var[$i],"open") Next EndIf Link to comment Share on other sites More sharing options...
James Posted January 27, 2010 Share Posted January 27, 2010 I'm using WinPE 3.0. This script opens the CD tray fine in XP, but not in WinPE. Any ideas or can someone confirm that it is not possible? How about you find out what the error is, then see why. $var = DriveGetDrive( "CDROM" ) If NOT @error Then For $i = 1 to $var[0] CDTray($var[$i],"open") Next Else ConsoleWrite(@error & @CRLF) EndIf Blog - Seriously epic web hosting - Twitter - GitHub - Cachet HQ Link to comment Share on other sites More sharing options...
sb1920alk Posted January 27, 2010 Author Share Posted January 27, 2010 How about you find out what the error is, then see why. No error. Running your code did nothing visible. I tried msgbox too, but still no. Then I ran the code below to make sure it was doing something. I get a message box with d: in it. So...it can list the drives, but the CDTray function isn't doing anything. Also, if I open Notepad, File->Open, right-click on the cd drive, and select "Eject", it really does eject, so WinPE has the ability to open the tray. I added @error to my message box and it's returning 0, so CDTray thinks it's locked or it's not a CD drive or something, even though DriveGetDrive says it is a CD drive. I'm not sure. $var = DriveGetDrive( "CDROM" ) If NOT @error Then For $i = 1 to $var[0] CDTray($var[$i],"open") MsgBox(0,"",$var[$i] & @CRLF & @error) Next Else MsgBox(0,"",@error) ConsoleWrite(@error & @CRLF) EndIf Link to comment Share on other sites More sharing options...
sb1920alk Posted January 28, 2010 Author Share Posted January 28, 2010 I have a solution now, so it's not a big deal. I tried adding the scripting package and running this vbscript: Const CDROM = 4 For Each d in CreateObject("Scripting.FileSystemObject").Drives If d.DriveType = CDROM Then Eject d.DriveLetter & ":\" End If Next Sub Eject(CDROM) Dim ssfDrives ssfDrives = 17 CreateObject("Shell.Application")_ .Namespace(ssfDrives).ParseName(CDROM).InvokeVerb("E&ject") End Sub ...but it did nothing. Since I already added the scripting package, I tried this: Set oWMP = CreateObject("WMPlayer.OCX.7" ) Set colCDROMs = oWMP.cdromCollection For i = 0 to colCDROMs.Count - 1 colCDROMs.Item(i).Eject Next ...but it errored (no WMP in WinPE). Running the original au3 as adminitrator didn't help. I stumbled across this link: http://memberwebs.com/stef/software/eject/eject.exe, and it worked fine. Obviously, I would prefer not to have to rely on a helper file, but it's good enough for now. If anyone can get the tray to open in WinPE 3.0 with pure AutoIT code, or vbscript, please let me know. Thanks, Link to comment Share on other sites More sharing options...
trancexx Posted January 28, 2010 Share Posted January 28, 2010 (edited) Try this: expandcollapse popupGlobal $sDriveLetter = "D:" ;<- correct letter of your CD drive Global $hFile = _OpenDrive($sDriveLetter) ; as getting handle _Eject($hFile) ; ejecting ; ...Close handle Func _OpenDrive($sDriveLetter) Local $aCall = DllCall("kernel32.dll", "ptr", "CreateFileW", _ "wstr", "\\.\" & $sDriveLetter, _ "dword", 0x80000000, _ ; GENERIC_READ "dword", 3, _ ; FILE_SHARE_READ|FILE_SHARE_WRITE "ptr", 0, _ "dword", 3, _ ; OPEN_EXISTING "dword", 0, _ ; SECURITY_ANONYMOUS "ptr", 0) If @error Or $aCall[0] = -1 Then Return SetError(1, 0, 0) EndIf Return $aCall[0] EndFunc ;==>_OpenDrive Func _Eject($hDriveHandle) Local $aCall = DllCall("kernel32.dll", "int", "DeviceIoControl", _ "ptr", $hDriveHandle, _ "dword", 0x2D4808, _ ; IOCTL_STORAGE_EJECT_MEDIA "ptr", 0, _ "dword", 0, _ "ptr", 0, _ "dword", 0, _ "dword*", 0, _ "ptr", 0) If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) EndIf Return 1 EndFunc ;==>_Eject Just set proper $sDriveLetter before. If that doesn't work then something is terribly wrong with your hardware. edit: Thing is AutoIt is using winmm.dll (mciSendStringW function) to do the job. Apparently on your system that's not working properly. AutoIt's way of oppening that door, translated to AutoIt for drive D, seems to be (speculation): DllCall("winmm.dll", "int", "mciSendStringW", "wstr", "open D: type cdaudio alias cd wait", "ptr", 0, "dword", 0, "ptr", 0) DllCall("winmm.dll", "int", "mciSendStringW", "wstr", "set cd door open wait", "ptr", 0, "dword", 0, "ptr", 0) DllCall("winmm.dll", "int", "mciSendStringW", "wstr", "close cd wait", "ptr", 0, "dword", 0, "ptr", 0) ;... Edited January 28, 2010 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
sb1920alk Posted January 28, 2010 Author Share Posted January 28, 2010 Try this: expandcollapse popupGlobal $sDriveLetter = "D:" ;<- correct letter of your CD drive Global $hFile = _OpenDrive($sDriveLetter) ; as getting handle _Eject($hFile) ; ejecting ; ...Close handle Func _OpenDrive($sDriveLetter) Local $aCall = DllCall("kernel32.dll", "ptr", "CreateFileW", _ "wstr", "\\.\" & $sDriveLetter, _ "dword", 0x80000000, _ ; GENERIC_READ "dword", 3, _ ; FILE_SHARE_READ|FILE_SHARE_WRITE "ptr", 0, _ "dword", 3, _ ; OPEN_EXISTING "dword", 0, _ ; SECURITY_ANONYMOUS "ptr", 0) If @error Or $aCall[0] = -1 Then Return SetError(1, 0, 0) EndIf Return $aCall[0] EndFunc ;==>_OpenDrive Func _Eject($hDriveHandle) Local $aCall = DllCall("kernel32.dll", "int", "DeviceIoControl", _ "ptr", $hDriveHandle, _ "dword", 0x2D4808, _ ; IOCTL_STORAGE_EJECT_MEDIA "ptr", 0, _ "dword", 0, _ "ptr", 0, _ "dword", 0, _ "dword*", 0, _ "ptr", 0) If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) EndIf Return 1 EndFunc ;==>_Eject Just set proper $sDriveLetter before.... That worked. Very nice...thank you. I much prefer code I can see rather than a black box like the exe above I found. I still wonder why CDTray didn't work. Link to comment Share on other sites More sharing options...
trancexx Posted January 28, 2010 Share Posted January 28, 2010 That worked. Very nice...thank you. I much prefer code I can see rather than a black box like the exe above I found. I still wonder why CDTray didn't work.Just debug that other code. Check errors and return values of the DllCalls and you will know why it doesn't work.You know how to do that? ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
sb1920alk Posted January 28, 2010 Author Share Posted January 28, 2010 Just debug that other code. Check errors and return values of the DllCalls and you will know why it doesn't work.You know how to do that?I have not worked with DllCalls much before. Link to comment Share on other sites More sharing options...
trancexx Posted January 28, 2010 Share Posted January 28, 2010 (edited) I have not worked with DllCalls much before. Something like this: expandcollapse popup#include <WinAPI.au3> ; FIRST CALL $aCall = DllCall("winmm.dll", "dword", "mciSendStringW", "wstr", "open D: type cdaudio alias cd wait", "ptr", 0, "dword", 0, "ptr", 0) If @error Then MsgBox(48, "Error", "DllCall function to mciSendStringW failed with first call" & @CRLF & "Error code number = " & @error) Else If $aCall[0] Then MsgBox(48, "Error", "mciSendStringW failed with first call" & @CRLF & "Error code number = " & _WinAPI_LoWord($aCall[0])) Else MsgBox(64, "First call ok", "mciSendStringW was successful with first call") EndIf EndIf ; SECOND CALL $aCall = DllCall("winmm.dll", "dword", "mciSendStringW", "wstr", "set cd door open wait", "ptr", 0, "dword", 0, "ptr", 0) If @error Then MsgBox(48, "Error", "DllCall function to mciSendStringW failed with second call" & @CRLF & "Error code number = " & @error) Else If $aCall[0] Then MsgBox(48, "Error", "mciSendStringW failed with second call" & @CRLF & "Error code number = " & _WinAPI_LoWord($aCall[0])) Else MsgBox(64, "Second call ok", "mciSendStringW was successful with second call") EndIf EndIf ; THIRD CALL $aCall = DllCall("winmm.dll", "dword", "mciSendStringW", "wstr", "close cd wait", "ptr", 0, "dword", 0, "ptr", 0) If @error Then MsgBox(48, "Error", "DllCall function to mciSendStringW failed with third call" & @CRLF & "Error code number = " & @error) Else If $aCall[0] Then MsgBox(48, "Error", "mciSendStringW failed with third call" & @CRLF & "Error code number = " & _WinAPI_LoWord($aCall[0])) Else MsgBox(64, "Third call ok", "mciSendStringW was successful with third call") EndIf EndIf ; Possible errors: http://msdn.microsoft.com/en-us/library/dd757162(VS.85).aspx edit: int -> dword Edited January 28, 2010 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
sb1920alk Posted January 28, 2010 Author Share Posted January 28, 2010 mciSendStringW failed with first call Error code number = 306 ...click OK... mciSendStringW failed with second call Error code number = 306 ...click OK... mciSendStringW failed with third call Error code number = 263 Link to comment Share on other sites More sharing options...
trancexx Posted January 29, 2010 Share Posted January 29, 2010 That's MCIERR_DEVICE_NOT_INSTALLED twice and the last one is MCIERR_INVALID_DEVICE_NAME. Derive conclusions yourself. ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
duncanchaos Posted April 21, 2010 Share Posted April 21, 2010 I need to find a way to do this under WinPE 64bit. There is no 32bit subsystem loading on one of my customer's WinPE 64bit boot CD and I need to find a way to eject the CD. The code in the earlier post makes a call to kernel32.dll. Is there a 64bit equivalent? Link to comment Share on other sites More sharing options...
trancexx Posted April 21, 2010 Share Posted April 21, 2010 I need to find a way to do this under WinPE 64bit. There is no 32bit subsystem loading on one of my customer's WinPE 64bit boot CD and I need to find a way to eject the CD. The code in the earlier post makes a call to kernel32.dll. Is there a 64bit equivalent?Did you try it? ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
AdmiralAlkex Posted April 21, 2010 Share Posted April 21, 2010 (edited) I need to find a way to do this under WinPE 64bit. There is no 32bit subsystem loading on one of my customer's WinPE 64bit boot CD and I need to find a way to eject the CD. The code in the earlier post makes a call to kernel32.dll. Is there a 64bit equivalent?What do you mean? If your exe is x64 then you're using the x64 kernel32.dll.On x64 windows x64 apps use \System32\, and x86 apps use \SysWOW64\ and to provide backwards compatibility it's all "automagically" redirected by WoW64.Here's some more reading:Programming Guide for 64-bit WindowsFile System RedirectorEdit: trancexx cheated! Edited April 21, 2010 by AdmiralAlkex .Some of my scripts: ShiftER, Codec-Control, Resolution switcher for HTC ShiftSome of my UDFs: SDL UDF, SetDefaultDllDirectories, Converting GDI+ Bitmap/Image to SDL Surface Link to comment Share on other sites More sharing options...
zorphnog Posted April 21, 2010 Share Posted April 21, 2010 I've ran into this exact issue running my scripts in WinPE a while back. This is what I use, works great for me. Func _EjectDisc() Local $sDrive, $aDrives, $oShell, $iTimer $aDrives = DriveGetDrive("all") If Not @error Then For $i = 1 To $aDrives[0] If DriveGetType($aDrives[$i] & "\") = "CDROM" Then $sDrive = StringUpper($aDrives[$i]) & "\" ExitLoop EndIf Next EndIf $oShell = ObjCreate("Shell.Application") $oShell.Namespace(17).ParseName($sDrive).InvokeVerb("Eject") $iTimer = TimerInit() While DriveStatus($sDrive) <> "NOTREADY" And TimerDiff($iTimer) < 10000 Sleep(10) WEnd EndFunc ;==>_EjectDisc The timeout loop at the end was added because the eject command does not block, so the timeout loop waits for the NOTREADY status on the drive or 10 seconds. Link to comment Share on other sites More sharing options...
Homes32 Posted September 24, 2010 Share Posted September 24, 2010 (edited) Try this: Global $sDriveLetter = "D:" ;<- correct letter of your CD drive Global $hFile = _OpenDrive($sDriveLetter) ; as getting handle _Eject($hFile) ; ejecting ; ...Close handle ...... noticed your comment in the code above. is it necessary to use CloseHandle() to free $hFile afterwords or not? Edited September 24, 2010 by Homes32 Link to comment Share on other sites More sharing options...
trancexx Posted September 25, 2010 Share Posted September 25, 2010 noticed your comment in the code above. is it necessary to use CloseHandle() to free $hFile afterwords or not?I's good practice to close opened handle when no longer needed. If you ejected the drive then close the handle. Not closing handles can lead to different problems with your application and even the whole system. Of course I don't mean one handle here, more like thousands.But luckily, when (leaking) app terminates, system clears the whole memory space of that process, releasing everything that process had locked. ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Homes32 Posted September 27, 2010 Share Posted September 27, 2010 I's good practice to close opened handle when no longer needed. If you ejected the drive then close the handle. Not closing handles can lead to different problems with your application and even the whole system. Of course I don't mean one handle here, more like thousands. But luckily, when (leaking) app terminates, system clears the whole memory space of that process, releasing everything that process had locked. ok thanks. for those interested here is the sister func to close the cdrom drive. use in conjunction with trancexx's post here Func _CloseTray($hDriveLetter) Local $aCall = DllCall("kernel32.dll", "int", "DeviceIoControl", _ "ptr", $hDriveLetter, _ "dword", 0x002D480C, _ ; IOCTL_STORAGE_LOAD_MEDIA "ptr", 0, _ "dword", 0, _ "ptr", 0, _ "dword", 0, _ "dword*", 0, _ "ptr", 0) If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) EndIf Return 1 EndFunc Link to comment Share on other sites More sharing options...
ModemJunki Posted March 6, 2012 Share Posted March 6, 2012 I realize this is an old topic but this really saved me a lot of time with a Windows PE task, so I will post both the Eject Tray and Close Tray functions using the same variables here. For sure the built-in CDTray function wasn't working in my PE environment, where it seems to work fine in my Windows environment. expandcollapse popup#include <WinAPI.au3> ;~ MJ ~; You should pass a drive letter to these functions, or you can fix it. ;~ MJ ~; I set mine as an EnvSet in my custom PE launcher because my internal client ;~ MJ ~; insisted on keeping ancient MS-DOS based batch files alive ;~ MJ ~; $drive = EnvGet("YourDriveHere") lots of ways to get a driveletter, $drive = "F:" Global $sDriveLetter = $drive Global $hFile = _OpenDrive($sDriveLetter) ; as getting handle _Eject($hFile) ; ejecting Sleep(5000); really you only need one function or the other, not both like this _CloseTray($hFile); closing _WinAPI_CloseHandle($hFile); ...Close handle ;~ MJ ~; Functions below ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Func _OpenDrive($sDriveLetter) Local $aCall = DllCall("kernel32.dll", "ptr", "CreateFileW", _ "wstr", "." & $sDriveLetter, _ "dword", 0x80000000, _ ; GENERIC_READ "dword", 3, _ ; FILE_SHARE_READ|FILE_SHARE_WRITE "ptr", 0, _ "dword", 3, _ ; OPEN_EXISTING "dword", 0, _ ; SECURITY_ANONYMOUS "ptr", 0) If @error Or $aCall[0] = -1 Then Return SetError(1, 0, 0) EndIf Return $aCall[0] EndFunc ;==>_OpenDrive Func _Eject($hDriveHandle) Local $aCall = DllCall("kernel32.dll", "int", "DeviceIoControl", _ "ptr", $hDriveHandle, _ "dword", 0x2D4808, _ ; IOCTL_STORAGE_EJECT_MEDIA "ptr", 0, _ "dword", 0, _ "ptr", 0, _ "dword", 0, _ "dword*", 0, _ "ptr", 0) If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) EndIf Return 1 EndFunc ;==>_Eject Func _CloseTray($hDriveHandle) Local $aCall = DllCall("kernel32.dll", "int", "DeviceIoControl", _ "ptr", $hDriveHandle, _ "dword", 0x002D480C, _ ; IOCTL_STORAGE_LOAD_MEDIA "ptr", 0, _ "dword", 0, _ "ptr", 0, _ "dword", 0, _ "dword*", 0, _ "ptr", 0) If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) EndIf Return 1 EndFunc ;==>_CloseTray Always carry a towel. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now