Champak Posted June 30, 2008 Share Posted June 30, 2008 (edited) 1/ The dialog that pops up when you put in a CD/DVD, how can I have my app recieve that notification, without doing some type of loop looking for that window? Can I recieve the same "signal" that is causing that dialog? 2/ How can I suppress that dialog/window? Edited June 30, 2008 by Champak Link to comment Share on other sites More sharing options...
weaponx Posted June 30, 2008 Share Posted June 30, 2008 ptrex has a script that checks for usb device change, you can probably use it for cdrom:http://www.autoitscript.com/forum/index.ph...hl=wmi++trigger Link to comment Share on other sites More sharing options...
Champak Posted July 1, 2008 Author Share Posted July 1, 2008 (edited) Thanks, that helps to an extent. I have it basically functioning how I want, however, can you/anyone see a way I can make this into an event function, instead of putting it in the loop? And, still looking for answer to "2" in OP. ((((CODE IN MY NEXT POST))))And if anyone is interested a lot of other CD rom functions available and ability to determine if ROM is writable or not...I've seen a few of those requests. http://msdn.microsoft.com/en-us/library/aa394081(VS.85).aspx Edited July 1, 2008 by Champak Link to comment Share on other sites More sharing options...
weaponx Posted July 1, 2008 Share Posted July 1, 2008 The only way I know to suppress the cd insert dialog is to disable auto-insert notification.http://www.base40.com/cdtTipAutoRun.htm Link to comment Share on other sites More sharing options...
AdmiralAlkex Posted July 1, 2008 Share Posted July 1, 2008 (edited) Are you talking about Explorers autostart?? If so maybe THIS helpsEdit: weaponx beat me to it Edited July 1, 2008 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...
Champak Posted July 1, 2008 Author Share Posted July 1, 2008 OK, so I decided instead of messing with the registry and other stuff, to just script it to hold down the shift key for a second. But two issues still remain, have this operate like an event...if that's possible, and get that first commented line working.."Not working as I think it should...investigate". Not a major issue, but I believe that it should cause less load/more efficient because it is going to a specific drive. Am I correct in thinking that? $strDrive = "F:" $objWMIService = ObjGet("winmgmts:\\.\root\cimv2") $colEvents = $objWMIService.ExecNotificationQuery _ ("Select * From __InstanceOperationEvent Within 5 Where " _ & "TargetInstance isa 'Win32_CDROMDrive'"); and " _ ; & "TargetInstance.Drive = " & $strDrive & "" );=========Not working as I think it should...investigate While 1 $objEvent = $colEvents.NextEvent If $objEvent.TargetInstance.MediaLoaded = True And $objEvent.TargetInstance.Drive = $strDrive Then Send("{SHIFTDOWN}") ;Test to see exactly what my drive is sayinggdHGDFGFDGJHG ConsoleWrite("!========================================================" & @CRLF) ConsoleWrite("1/ " & $objEvent.TargetInstance.MediaLoaded & @CRLF) ConsoleWrite("3/ " & $objEvent.TargetInstance.DeviceID & @CRLF) ConsoleWrite("4/ " & $objEvent.TargetInstance.Description & @CRLF) ConsoleWrite("5/ " & $objEvent.TargetInstance.VolumeName & @CRLF);Will need this in the function to be created ConsoleWrite("6/ " & $objEvent.TargetInstance.VolumeSerialNumber & @CRLF);Will need this in the function to be created ConsoleWrite("12/ " & $objEvent.TargetInstance.Caption & @CRLF) ConsoleWrite("!========================================================" & @CRLF) Sleep(1000);Set up function that sleeps based on CPU load Send("{SHIFTUP}") EndIf WEnd Link to comment Share on other sites More sharing options...
Champak Posted July 2, 2008 Author Share Posted July 2, 2008 It seems that the first thing in the loop "$objEvent = $colEvents.NextEvent" is pausing the script and waiting to receive the event. That totally messes up my plans for this code as it renders the rest of my app useless. I know you can assign timeout values to it, but that would cause hickups and sluggish responses because it would happen every go round. So I'm definately in need of this strictly acting like a "regular" event function. Is there a way to do this? Link to comment Share on other sites More sharing options...
weaponx Posted July 2, 2008 Share Posted July 2, 2008 Maybe the WMI even notification just wont work for you. I would just use straight WMI to poll the drive every so often. You could use adlib so your script could continue. 1. Store beginning state. (MediaLoaded) 2. If MediaLoaded = -1 then store VolumeSerialNumber into a global var 3. Use adlib to call the function at a set interval, comparing the VolumeSerialNumber expandcollapse popup$strComputer = "localhost" $Output="" $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2") $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_CDROMDrive", "WQL", 0x10+0x20) If IsObj($colItems) then For $objItem In $colItems $Output &= "Availability: " & $objItem.Availability & @CRLF $strCapabilities = $objItem.Capabilities(0) $Output &= "Capabilities: " & $strCapabilities & @CRLF $strCapabilityDescriptions = $objItem.CapabilityDescriptions(0) $Output &= "CapabilityDescriptions: " & $strCapabilityDescriptions & @CRLF $Output &= "Caption: " & $objItem.Caption & @CRLF $Output &= "CompressionMethod: " & $objItem.CompressionMethod & @CRLF $Output &= "ConfigManagerErrorCode: " & $objItem.ConfigManagerErrorCode & @CRLF $Output &= "ConfigManagerUserConfig: " & $objItem.ConfigManagerUserConfig & @CRLF $Output &= "CreationClassName: " & $objItem.CreationClassName & @CRLF $Output &= "DefaultBlockSize: " & $objItem.DefaultBlockSize & @CRLF $Output &= "Description: " & $objItem.Description & @CRLF $Output &= "DeviceID: " & $objItem.DeviceID & @CRLF $Output &= "Drive: " & $objItem.Drive & @CRLF $Output &= "DriveIntegrity: " & $objItem.DriveIntegrity & @CRLF $Output &= "ErrorCleared: " & $objItem.ErrorCleared & @CRLF $Output &= "ErrorDescription: " & $objItem.ErrorDescription & @CRLF $Output &= "ErrorMethodology: " & $objItem.ErrorMethodology & @CRLF $Output &= "FileSystemFlags: " & $objItem.FileSystemFlags & @CRLF $Output &= "FileSystemFlagsEx: " & $objItem.FileSystemFlagsEx & @CRLF $Output &= "Id: " & $objItem.Id & @CRLF $Output &= "LastErrorCode: " & $objItem.LastErrorCode & @CRLF $Output &= "Manufacturer: " & $objItem.Manufacturer & @CRLF $Output &= "MaxBlockSize: " & $objItem.MaxBlockSize & @CRLF $Output &= "MaximumComponentLength: " & $objItem.MaximumComponentLength & @CRLF $Output &= "MaxMediaSize: " & $objItem.MaxMediaSize & @CRLF $Output &= "MediaLoaded: " & $objItem.MediaLoaded & @CRLF ;<<<<<<<<<<<<<<<<<<<< CHECK FOR CHANGE (0 = Empty, -1 = CD Inserted) $Output &= "MediaType: " & $objItem.MediaType & @CRLF $Output &= "MfrAssignedRevisionLevel: " & $objItem.MfrAssignedRevisionLevel & @CRLF $Output &= "MinBlockSize: " & $objItem.MinBlockSize & @CRLF $Output &= "Name: " & $objItem.Name & @CRLF $Output &= "NeedsCleaning: " & $objItem.NeedsCleaning & @CRLF $Output &= "NumberOfMediaSupported: " & $objItem.NumberOfMediaSupported & @CRLF $Output &= "PNPDeviceID: " & $objItem.PNPDeviceID & @CRLF $strPowerManagementCapabilities = $objItem.PowerManagementCapabilities(0) $Output &= "PowerManagementCapabilities: " & $strPowerManagementCapabilities & @CRLF $Output &= "PowerManagementSupported: " & $objItem.PowerManagementSupported & @CRLF $Output &= "RevisionLevel: " & $objItem.RevisionLevel & @CRLF $Output &= "SCSIBus: " & $objItem.SCSIBus & @CRLF $Output &= "SCSILogicalUnit: " & $objItem.SCSILogicalUnit & @CRLF $Output &= "SCSIPort: " & $objItem.SCSIPort & @CRLF $Output &= "SCSITargetId: " & $objItem.SCSITargetId & @CRLF $Output &= "Size: " & $objItem.Size & @CRLF $Output &= "Status: " & $objItem.Status & @CRLF $Output &= "StatusInfo: " & $objItem.StatusInfo & @CRLF $Output &= "SystemCreationClassName: " & $objItem.SystemCreationClassName & @CRLF $Output &= "SystemName: " & $objItem.SystemName & @CRLF $Output &= "TransferRate: " & $objItem.TransferRate & @CRLF $Output &= "VolumeName: " & $objItem.VolumeName & @CRLF ;<<<<<<<<<<<<<<<<<<<< CHECK FOR CHANGE $Output &= "VolumeSerialNumber: " & $objItem.VolumeSerialNumber & @CRLF ;<<<<<<<<<<<<<<<<<<<< CHECK FOR CHANGE ConsoleWrite($Output) $Output="" Next Else Msgbox(0,"WMI Output","No WMI Objects Found for class: " & "Win32_CDROMDrive" ) Endif Link to comment Share on other sites More sharing options...
Champak Posted July 7, 2008 Author Share Posted July 7, 2008 (edited) This is cool. Thanks. But when activated, if a CD/DVD is inserted, it causes the script to pause for about 5-10 seconds while the CD loads. This can be problematic with other functions that might miss an activation point.In looking at that I found this:http://msdn.microsoft.com/en-us/library/aa393867(VS.85).aspxDoesn't that allow for what I'm trying to do...to react like an object event like I've been trying to do so it doesn't pause/slow up the rest of the script? I just either couldn't get the "objWbemSink" routine, or it isn't what I think. Am I on the right track, or is it not what I think/can't work with autoit?Also, is there a way to go directly to what I want without enumerating everything/what I want by ways of a loop? Like get the "$objItem.DeviceID" without doing a loop? Edited July 7, 2008 by Champak Link to comment Share on other sites More sharing options...
Champak Posted July 11, 2008 Author Share Posted July 11, 2008 Bump Link to comment Share on other sites More sharing options...
SkinnyWhiteGuy Posted July 11, 2008 Share Posted July 11, 2008 This is something I've been playing with, it might help you do what you want. Change the Logical Disk to CD-ROM if you want, it may work better like that. ;WMI monitoring $wbemFlagReturnImmediately = 0x10 $wbemFlagForwardOnly = 0x20 Dim $strComputer, $SINK, $objWMIService $strComputer = "127.0.0.1" $SINK = ObjCreate("WbemScripting.SWbemSink") ObjEvent($SINK, "SINK_") $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2") If Not @error Then $objWMIService.ExecNotificationQueryAsync ($SINK, "SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_LogicalDisk' AND TargetInstance.DriveType = 5") Else ConsoleWrite("Error encountered. Error Code was " & @error & ".") Exit EndIf ConsoleWrite("In monitoring mode. Press Ctrl+C to exit." & @CRLF) While 1 Sleep(10000) WEnd ;****************************************************************************** Func SINK_OnObjectReady($objLatestEvent, $objAsyncContext) If $objLatestEvent.TargetInstance.VolumeName <> "" Then ;Trap asynchronous events. $output = "DeviceID: " & $objLatestEvent.TargetInstance.DeviceID & @CRLF $output &= "FileSystem: " & $objLatestEvent.TargetInstance.FileSystem & @CRLF $output &= "VolumeName: " & $objLatestEvent.TargetInstance.VolumeName & @CRLF ToolTip($output, (@DesktopWidth - 250), (@DesktopHeight - 100), "CD/DVD Inserted") EndIf EndFunc ;==>SINK_OnObjectReady Link to comment Share on other sites More sharing options...
weaponx Posted July 11, 2008 Share Posted July 11, 2008 This is what I came up with. Only problem is that WMI likes to error out while getting the serial number immediately after the window message is received... expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Opt("GUIOnEventMode", 1) ; Change to OnEvent mode Global Const $SourceDrive = "d:" Global $LastSerial = GetSerial($SourceDrive) ConsoleWrite("LastSerial: " & $LastSerial & @CRLF) GUIRegisterMsg (0x0219, "Check") ;WM_DEVICECHANGE ;Create GUI $mainwindow = GUICreate("CD Status", 200, 100) GUISetOnEvent($GUI_EVENT_CLOSE, "Quit") $okbutton = GUICtrlCreateButton("Exit", 70, 50, 60) GUICtrlSetOnEvent($okbutton, "Quit") GUISetState(@SW_SHOW) While 1 Sleep(1000) ; Idle around WEnd Func Quit() Exit EndFunc ;Callback for WM_DEVICECHANGE Func Check($hWndGUI, $MsgID, $WParam, $LParam) Local $NewSerial ConsoleWrite("Device change detected" & @CRLF) ;ConsoleWrite("hWndGUI: " & $hWndGUI & @CRLF) ;ConsoleWrite("MsgID: " & $MsgID & @CRLF) ;ConsoleWrite("WParam: " & $WParam & @CRLF) ;ConsoleWrite("LParam: " & $LParam & @CRLF) Switch $WParam Case 0x00008004 ConsoleWrite("A device or piece of media has been removed." & @CRLF) Case 0x00008000 ConsoleWrite("A device or piece of media has been inserted and is now available." & @CRLF) $NewSerial = GetSerial($SourceDrive) Switch @ERROR Case 1 ConsoleWrite("Error connecting to WMI" & @CRLF) Case 2 ConsoleWrite("Error retrieving serial number from WMI" & @CRLF) EndSwitch CompareSerial($LastSerial,$NewSerial) EndSwitch ConsoleWrite(@CRLF) EndFunc ;Compare serial number of previous CD to current Func CompareSerial($previous, $current) If $previous <> $current Then $LastSerial = $current MsgBox(0,"","A CD has been inserted with serial number " & $current) EndIf EndFunc ;Retrieve serial number from CD media Func GetSerial($DriveLetter) Local $strComputer = "localhost" Local $Output="" Local $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2") If @ERROR Then Return SetError(1,0,"") Local $colItems = $objWMIService.ExecQuery("SELECT MediaLoaded,VolumeName,VolumeSerialNumber FROM Win32_CDROMDrive WHERE Drive = '" & $DriveLetter & "'" , "WQL", 0x10+0x20) If IsObj($colItems) then For $objItem In $colItems $Output &= "MediaLoaded: " & $objItem.MediaLoaded & @CRLF ;<<<<<<<<<<<<<<<<<<<< CHECK FOR CHANGE (0 = Empty, -1 = CD Inserted) $Output &= "VolumeName: " & $objItem.VolumeName & @CRLF ;<<<<<<<<<<<<<<<<<<<< CHECK FOR CHANGE $Output &= "VolumeSerialNumber: " & $objItem.VolumeSerialNumber & @CRLF ;<<<<<<<<<<<<<<<<<<<< CHECK FOR CHANGE ConsoleWrite($Output) Return $objItem.VolumeSerialNumber $Output="" Next Else Return SetError(2,0,"") Endif ;Return NULL if an invalid drive letter is passed or cd tray is empty Return "" EndFunc Link to comment Share on other sites More sharing options...
Champak Posted July 11, 2008 Author Share Posted July 11, 2008 Thanks, I'll look into this. Link to comment Share on other sites More sharing options...
Champak Posted July 21, 2008 Author Share Posted July 21, 2008 (edited) @SkinnyWhiteGuy That's great. It works as it should (generally). The problem is, it seems to be causing a problem with a program/resource, I notice in the task manager, wmiprvse.exe. I've NEVER noticed load on this program before, but since I've put this code in, I notice that the cpu load on this goes up to 33% and pretty much hovers there (This is random an I can't reproduce it EVERY time) and I can't end the task...either by closing the script or end task in the TM. Is there a way to fix this? The following is my set up, note I took out the top WMI declarations, I didn't see a purpose in them...was I wrong in that? expandcollapse popup$SINK = ObjCreate("WbemScripting.SWbemSink") ObjEvent($SINK, "_CDROMCheck_") $oCDROMCheck = ObjGet("winmgmts:\\.\root\CIMV2") $oCDROMCheck.ExecNotificationQueryAsync ($SINK, "SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_CDROMDrive' AND TargetInstance.Drive = 'e:'");"d:\" If IsObj($oCDROMCheck) Then Global $CD_New Else ConsoleWrite("! No WMI Objects Found for class: Win32_CDROMDrive to check CDROM status" & @CRLF) Endif Func _CDROMCheck_OnObjectReady($objLatestEvent, $objAsyncContext) If GUICtrlRead($WMP_MediaSelectOption+1) = $CD_Mode Or GUICtrlRead($WMP_MediaSelectOption+1) = $DVD_Mode And IsObj($oCDROMCheck) then If $objLatestEvent.TargetInstance.VolumeName <> "" Then ;Trap asynchronous events. GUICtrlSetData($WMP_SongInfo, "CD/DVD has been loaded. Press play.") ;============================ ; $Output = "Caption: " & $objLatestEvent.TargetInstance.Caption & @CRLF ; $Output &= "Description: " & $objLatestEvent.TargetInstance.Description & @CRLF ; $Output &= "SystemName: " & $objLatestEvent.TargetInstance.SystemName & @CRLF ; $Output &= "DeviceID: " & $objLatestEvent.TargetInstance.DeviceID & @CRLF ; $Output &= "VolumeName: " & $objLatestEvent.TargetInstance.VolumeName & @CRLF ; $Output &= "VolumeSerialNumber: " & $objLatestEvent.TargetInstance.VolumeSerialNumber & @CRLF ; ConsoleWrite($Output) ; $Output="" ;============================ ;Prevent the window that allows you to select a program to play CD/DVD from popping up ;NOTE: If not in CD/DVD mode, the window will still pop up. Send("{shiftdown}") $CDROMCheckRelease = _Timer_SetTimer($GUIMain, 2500, "_CDROMCheck_Release") ElseIf $objLatestEvent.TargetInstance.VolumeName = "" And $CD_New = 0 Then GUICtrlSetData($WMP_SongInfo, "No CD/DVD in ROM to play or tray is open. Insert CD/DVD then press play.") $CD_New = 1 EndIf EndIf EndFunc ;==>SINK_OnObjectReady Func _CDROMCheck_Release($hWnd, $Msg, $iIDTimer, $dwTime);Release the shiftdown set by _CDROMCheck_OnObjectReady Send("{shiftup}") _Timer_KillTimer($GUIMain, $CDROMCheckRelease) EndFunc If I can't fix this, I would have to go with weaponx's version. EDIT: It MAY be do to running the script multiple times and the accumulation of opening this sinkobject "lookout" raises the cpu load on the wmiprvse.exe. I don't know, just a theory since I don't really see this load on the first run of the app. IF that is the case, then there would have to be a way to kill the function on exit. Edited July 21, 2008 by Champak Link to comment Share on other sites More sharing options...
Champak Posted July 22, 2008 Author Share Posted July 22, 2008 OK, I've confirmed, it is definitely because of some type of accumulation. I thought Autoit is suppose to kill/release anything it uses upon exiting. I tried "resetting" the objects to a variable equaling "0" before exiting, but that didn't help. Link to comment Share on other sites More sharing options...
Champak Posted July 24, 2008 Author Share Posted July 24, 2008 I've solved the problem. I put this: "$SINK.Cancel()" in an exit function, and that solved it....as far as I've tested it. I've restarted the app numerous times and I see no build up. Link to comment Share on other sites More sharing options...
Champak Posted August 1, 2008 Author Share Posted August 1, 2008 The "$SINK.Cancel()" works ok, however upon an unexpected exit, where the app exits without calling the exit function, the "$SINK.Cancel()" isn't activated and thus doesn't clear the cpu load. Even when restarted and then exited properly, it isn't cleared. Any suggestion to "backup" the "$SINK.Cancel()" in case of an unexpected exit? 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