Epulsar Unidad - controlar bucle?

Pregunta Sin Miedo no te cortes cualquier cosa para empezar - Autoit se comienza facilmente.Para Ordenes o Comandos sueltos. Ver nota como preguntar.
Responder
Avatar de Usuario
yasmany
Hacker del Foro
Mensajes: 249
Registrado: 06 Sep 2011, 21:30

Epulsar Unidad - controlar bucle?

Mensaje por yasmany »

Un buen día a todos, resulta que dentro de mi aplicación Antivirus tengo la función de actualizar combo de unidades, es decir constantemente revisa si existe una unidad y la agrega al combo claro que primero compara si esta ya existe en el combo, si existe no la agrega.
Al igual revisa si la unidades que constan en el combo estan READY "legibles/existen" si no existen la elimina del combo basandose en el index.
El problema está en que cuando quiero expulsar una unidad desde la bandeja de notificaciones no me lo permite en la mayoría de veces (90 de 100) debido a que se está ocupando, ciertamente lo es. ya que mi aplicación lo hace.
¿Como podría solucionar el problema?
Espero su pronta ayuda, gracias. :smt024

Ubico el code de la funcion: ésta la llamo constatemente en el bucle que captura los eventos dentro de la GUI. (While and WEnd)

Código: Seleccionar todo

Func actualizarComboDeUnidades()
	Local $i, $var, $dato, $count, $val, $resultado, $state
	For $i = 0 To _GUICtrlComboBox_GetCount($cbUnidades) - 1
		$dato = _GUICtrlComboBox_GetLBText($cbUnidades, $i, $sText)

		If $sText <> "BUSCAR UNIDAD..." Then
			valordefinido2()

			If DriveStatus($unidad) <> "READY" Then
				If GUICtrlRead($cbUnidades) = $sText Then
					_GUICtrlComboBox_DeleteString($cbUnidades, $i)
					ActualizarGui()
				Else
					_GUICtrlComboBox_DeleteString($cbUnidades, $i)
				EndIf
			EndIf
		EndIf
	Next

	If GUICtrlRead($chbxUnidades) = $GUI_CHECKED Then; si está checkeado
		$val = DriveGetDrive("ALL")
	Else
		$val = DriveGetDrive("REMOVABLE")
	EndIf
	If Not @error Then

		For $count = 1 To $val[0]
			If DriveStatus($val[$count]) <> "READY" Then
			Else
				If GUICtrlRead($chbxHomeDrive) = $GUI_UNCHECKED Then
					$valHomeDrive = @HomeDrive
				Else
					$valHomeDrive = ""

				EndIf

				If $val[$count] <> $valHomeDrive Then; Or $val[$count] <> $valHomeDrive Then

					$resultado = StringUpper(DriveGetLabel($val[$count]) & "(" & $val[$count] & ")")
					If _GUICtrlComboBox_FindStringExact($cbUnidades, $resultado) = "-1" Then
						_GUICtrlComboBox_ShowDropDown($cbUnidades, False)
						_GUICtrlComboBox_AddString($cbUnidades, $resultado)

						valordefinido3($resultado)
						escaner()
						If $valor <> 0 Then
							$valor = ""
							TrayTip("Avy Antivirus", "Unidad reciente" & @CRLF & $resultado & @CRLF & "Se a encontrado algunos registros.", 1, 2)
							_GUICtrlComboBox_SelectString($cbUnidades, $resultado)
							Clic_combo()
							Clic_Analizar()

							If GUICtrlRead($chekboxdsa) <> $GUI_CHECKED Then
								$state = WinGetState("Avy Antivirus ", "")
								If BitAND($state, 16) Then; si la ventana esta minimizada
									WinSetState("Avy Antivirus ", "", @SW_RESTORE)
								ElseIf BitAND($state, 2) Then; Si es visible no hacer nada

								ElseIf BitAND($state, 4) Then
									GUISetState(@SW_SHOW)
									gui()
									ExitLoop
								EndIf
							ElseIf GUICtrlRead($chekboxdsa) = $GUI_CHECKED Then
								If DriveGetType($unidad) = "Removable" Then; solo a las unidades removibles desinfecto de forma automática
									Clic_Desinfectar()
								EndIf
							EndIf
						Else
							$tray = TrayTip("Avy Antivirus", "Unidad reciente" & @CRLF & $resultado & @CRLF & "UNIDAD LIMPIA, NO SE ENCONTRARON REGISTROS.", 1, 1)
							GUICtrlSetBkColor($tray, 0x00ff00)
						EndIf
					Else
					EndIf
				EndIf

			EndIf
		Next
	EndIf
EndFunc   ;==>actualizarComboDeUnidades
NOTA: Si tienen varias sugerencias o ayuda, les agradecería. :smt024
Obra de modo que merezcas a tu propio juicio y a juicio de los demás la eternidad, que te hagas insustituible que no merezcas morir.
https://www.facebook.com/yasmanycurimilma
Avatar de Usuario
yasmany
Hacker del Foro
Mensajes: 249
Registrado: 06 Sep 2011, 21:30

Re: Epulsar Unida - controlar bucle?

Mensaje por yasmany »

Alguien en conectado?
Obra de modo que merezcas a tu propio juicio y a juicio de los demás la eternidad, que te hagas insustituible que no merezcas morir.
https://www.facebook.com/yasmanycurimilma
Avatar de Usuario
arkcrew
Profesional del Autoit
Mensajes: 506
Registrado: 28 Sep 2009, 19:17
Ubicación: Granada, España
Contactar:

Re: Epulsar Unida - controlar bucle?

Mensaje por arkcrew »

Yo suelo pasarme por aquí a diario, pero no se que unidad quieres expulsar. Una unidad flash? Si es así no vas a poder hacerlo si tienes algún proceso operando sobre estas, tienes que cerrar las operaciones que tengas abiertas sobre las unidades y expulsarlas después.

Saludos
Avatar de Usuario
yasmany
Hacker del Foro
Mensajes: 249
Registrado: 06 Sep 2011, 21:30

Re: Epulsar Unida - controlar bucle?

Mensaje por yasmany »

Como podría modificar el code para que no suceda esto continuamente, habrá alguna manera.
Existe esta opción que detecta unidades agregadas y las que se remuevan sean discos externos o PenDrives unicamente
Pero tarda al menos unos 3 segundos en detectar el evento de sustracción o inserción de una unidad, pero permite expulsar normalmente la memoria :smt001 .

Código: Seleccionar todo

$DBT_DEVICEARRIVAL = "0x00008000"
$WM_DEVICECHANGE = 0x0219
$strComputer = "."
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")
$colEvents = $objWMIService.ExecNotificationQuery("Select * From __InstanceOperationEvent Within 5 Where " & "TargetInstance isa 'Win32_LogicalDisk'")

While 1
	$objEvent = $colEvents.NextEvent
	If $objEvent.TargetInstance.DriveType = 2 Then
		Select
			Case $objEvent.Path_.Class() = "__InstanceCreationEvent"
				ConsoleWrite("Drive " & $objEvent.TargetInstance.DeviceId & "has been added." & @CR);A Usb drive has been plugged in
			Case $objEvent.Path_.Class() = "__InstanceDeletionEvent"
				ConsoleWrite("Drive " & $objEvent.TargetInstance.DeviceId & "has been removed." & @CR);A usb drive has been removed
		EndSelect
	EndIf
WEnd
Habrá como emplear otro método diferente :smt024
Obra de modo que merezcas a tu propio juicio y a juicio de los demás la eternidad, que te hagas insustituible que no merezcas morir.
https://www.facebook.com/yasmanycurimilma
Avatar de Usuario
arkcrew
Profesional del Autoit
Mensajes: 506
Registrado: 28 Sep 2009, 19:17
Ubicación: Granada, España
Contactar:

Re: Epulsar Unida - controlar bucle?

Mensaje por arkcrew »

A ver, tres segundos es un retardo muy mínimo, si quieres un lapso menor, te recomiendo que metas la llamada a tu función en un timer task y que de alguna forma controles cuando el usuario se desplaza al area de notificación donde se encuentras las unidades, así por ejemplo podrías pausar tu tarea para que el usuario pueda expulsar la unidad correctamente. Es una idea vamos, a lo muy cutre puedes hacerlo incluso con las coordenadas del mouse xD

Saludos

PD: Si hablo de funciones con nombres raros es porque tengo veinte mil lenguajes en la cabeza y no doy pie con bola, pero en Autoit existen los timer task, se llaman AdlibRegister o algo así creo recordar
Avatar de Usuario
yasmany
Hacker del Foro
Mensajes: 249
Registrado: 06 Sep 2011, 21:30

Re: Epulsar Unida - controlar bucle?

Mensaje por yasmany »

El retardo de 3 segundos implica tambien el retardo de la GUI en reaccionar a un clic.
Si me redireccionara de acuerdo a las coordenadas del mouse, hay que tener en cuenta que algunos usuarios tienen la barra del area de notificacion alineado en diferentes lugares, no siempre sera en la parte de abajo, pero podría tener el nombre de Class AU3Info = ToolbarWindow32, pero tambien creo tendría consecuencias de lentitud en los eventos que vaya a realizar. :smt024
Obra de modo que merezcas a tu propio juicio y a juicio de los demás la eternidad, que te hagas insustituible que no merezcas morir.
https://www.facebook.com/yasmanycurimilma
Avatar de Usuario
arkcrew
Profesional del Autoit
Mensajes: 506
Registrado: 28 Sep 2009, 19:17
Ubicación: Granada, España
Contactar:

Re: Epulsar Unida - controlar bucle?

Mensaje por arkcrew »

Es lo malo de la programación que no es multihilo, de todas formas el lapso de tres segundos puedes controlarlo con una buena sincronización de las tareas y no es "tanto" como para preocuparse, esos tres segundos bien optimizados puedes reducirlos a 2 o algo menos incluso si estructuras bien tu código. Además debe existir alguna forma de comprobar el estado de una unidad sin tener que estár bloqueándola, alguna dll o algo

Saludos
PDF
Hacker del Foro
Mensajes: 152
Registrado: 18 Ene 2013, 23:23

Re: Epulsar Unida - controlar bucle?

Mensaje por PDF »

Hola, también suelo pasarme a diario por aquí...

La verdad no creo que el problema este en la forma que haces para detectar los usb's conectados o desconectados, creo que esto puede ocurrir cuando no cierras un identificador de fichero en el momento de utilizarlo por completo, estos identificadores son devueltos por las funciones FileOpen y FileFindFirstFile principalmente, si los utilizas en tu aplicación deberías de comprobar que los cierras con FileClose, con esto la unidad debería de quedar liberada para ser expulsada..

Saludos..
Avatar de Usuario
yasmany
Hacker del Foro
Mensajes: 249
Registrado: 06 Sep 2011, 21:30

Re: Epulsar Unida - controlar bucle?

Mensaje por yasmany »

Mil gracias por vuestra ayuda, arckcrew y PDF .
De acuerdo con lo que dices PDF, me suponía que eso puede ser el problema, voy a revisar.
Saludos. :smt024
Obra de modo que merezcas a tu propio juicio y a juicio de los demás la eternidad, que te hagas insustituible que no merezcas morir.
https://www.facebook.com/yasmanycurimilma
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Epulsar Unida - controlar bucle?

Mensaje por Chefito »

Seguramente te pasa eso por lo que dice el compañero PDF, porque por revisar cada cierto tiempo como está el dispositivo usb no debe bloquearlo :smt001 .
Igualmente ya te respondí en otro post otras dos posibilidades mejores que lo que has hecho, una es la que has puesto en tu segundo post, y la que pienso que es mejor, aunque algo más complicada es la segunda que te presento en este post: http://www.emesn.com/autoitforum/viewto ... =usb#p8005

Pero lo dicho, te contesté en este otro post: http://www.emesn.com/autoitforum/viewto ... usb#p12093
Por favor, buscar en el buscador que esta casi todo resuelto, o casi resuelto :smt023 .

El código un poquitín adaptado sería:

Código: Seleccionar todo

Global Const $DBT_DEVICEREMOVECOMPLETE = "0x00008004"
Dim $USB_ATTENTION = "0x00000007"

Global Const $DBT_DEVICEARRIVAL     = 0x00008000
Global Const $WM_DEVICECHANGE       = 0x0219
Global Const $tagDEV_BROADCAST_HDR  = "dword dbchsize;dword dbchdevicetype;dword dbchreserved"
Global Const $DBT_DEVTYP_VOLUME     = 0x00000002
Global Const $tagDEV_BROADCAST_VOLUME   = "dword dbcvsize;dword dbcvdevicetype;dword dbcvreserved;dword dbcvunitmask;short dbcvflags"
Global Const $DBTF_MEDIA            = 0x0001
Global Const $DBTF_NET              = 0x0002
;Setup The GUI to watch for the DeviceChange Event

GUICreate("Test")
GUIRegisterMsg($WM_DEVICECHANGE, "DeviceChange")

While 1
    Sleep (1000)
WEnd

Func DeviceChange($hWndGUI, $MsgID, $WParam, $LParam)
   ;ConsoleWrite($wparam)
    $iEvent = $WParam
	If $iEvent=$DBT_DEVICEREMOVECOMPLETE Then
            $temp = DllStructCreate($tagDEV_BROADCAST_HDR, $LParam)
            $iDeviceType = DllStructGetData($temp, "dbchdevicetype")
            If $iDeviceType = $DBT_DEVTYP_VOLUME Then
                $struct = DllStructCreate($tagDEV_BROADCAST_VOLUME, $LParam)
                $iUnitMask = DllStructGetData($struct, "dbcvunitmask")
                $iFlags = DllStructGetData($struct, "dbcvflags")
                If Not BitAND($iFlags, $DBTF_MEDIA) And Not BitAND($iFlags, $DBTF_NET) Then
                    $sDrive = FirstDriveFromMask($iUnitMask)
                    ConsoleWrite($sDrive & ": ha sido quitado o removido!" & @CRLF)
                EndIf
            EndIf
	EndIf
    If $iEvent = $DBT_DEVICEARRIVAL Then
            $temp = DllStructCreate($tagDEV_BROADCAST_HDR, $LParam)
            $iDeviceType = DllStructGetData($temp, "dbchdevicetype")
            If $iDeviceType = $DBT_DEVTYP_VOLUME Then
                $struct = DllStructCreate($tagDEV_BROADCAST_VOLUME, $LParam)
                $iUnitMask = DllStructGetData($struct, "dbcvunitmask")
                $iFlags = DllStructGetData($struct, "dbcvflags")
                If Not BitAND($iFlags, $DBTF_MEDIA) And Not BitAND($iFlags, $DBTF_NET) Then
                    $sDrive = FirstDriveFromMask($iUnitMask)
                    ConsoleWrite($sDrive & ": ha sido insertado!" & @CRLF)
                EndIf
            EndIf
    EndIf
EndFunc   ;==>DeviceChange

Func FirstDriveFromMask($unitmask)
    Local $i
    For $i = 0 To 25
        If BitAND($unitmask, 0x1) Then ExitLoop
        $unitmask = BitShift($unitmask, 1)
    Next
    Return Chr($i + Asc('A'))
EndFunc
Este código es el mejor, porque no tienes que comprobarlo cada cierto tiempo. Va por eventos. Te despreocupas de tener que meterlo en un bucle y que funcione bien :smt003 .

Buscando poquito en google, puedes mirar todo lo referente a este código y mucho más: http://msdn.microsoft.com/en-us/library ... s.85).aspx
Microsoft lo sabe todo de windows :smt005 .

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
yasmany
Hacker del Foro
Mensajes: 249
Registrado: 06 Sep 2011, 21:30

Re: Epulsar Unida - controlar bucle?

Mensaje por yasmany »

Excelente ayuda :smt001 , mil gracias chefito una vez mas, pero surge un inconveniente que detecta unidades que no son legibles, bueno aparecen en el equipo pero al abrirlas no son accesibles.
Como podria evitar que no detecte aquellas unidades que no estan READY?.
Obra de modo que merezcas a tu propio juicio y a juicio de los demás la eternidad, que te hagas insustituible que no merezcas morir.
https://www.facebook.com/yasmanycurimilma
Avatar de Usuario
yasmany
Hacker del Foro
Mensajes: 249
Registrado: 06 Sep 2011, 21:30

Re: Epulsar Unida - controlar bucle?

Mensaje por yasmany »

Disculpa mi boba pregunta ya lo tengo resuelto.

Código: Seleccionar todo

$sDrive = FirstDriveFromMask($iUnitMask)
If DriveStatus($sDrive&":") == "READY" Then
     ConsoleWrite($sDrive & ": ha sido insertado!" & @CRLF)
EndIf
Una pregunta mas como puedo hacer para que cuando ejecuto el script me detecte las unidades actuales, ya que detecta las que son removidos y los que actualmente se ingrese despues de ejecutar el Script.

Saludos... :smt024
Obra de modo que merezcas a tu propio juicio y a juicio de los demás la eternidad, que te hagas insustituible que no merezcas morir.
https://www.facebook.com/yasmanycurimilma
PDF
Hacker del Foro
Mensajes: 152
Registrado: 18 Ene 2013, 23:23

Re: Epulsar Unidad - controlar bucle?

Mensaje por PDF »

Hola..

Lo puedes hacer de la manera como lo estabas haciendo con DriveGetDrive, solo que tendrás que ubicarlo en otra parte del script, en otra función distinta a la del evento y llamarla luego de crear la GUI...

Saludos
Avatar de Usuario
yasmany
Hacker del Foro
Mensajes: 249
Registrado: 06 Sep 2011, 21:30

Re: Epulsar Unidad - controlar bucle?

Mensaje por yasmany »

Gracias PDF, lo que hice es que cada vez que detecte una unidad llame a la fucion ActualizarComboDeUnidades. bueno el problema se solucionó satisfactoriamente :smt001
He acabado de realizar la ayuda para el programa: http://www.emesn.com/autoitforum/viewto ... 634#p16634
Obra de modo que merezcas a tu propio juicio y a juicio de los demás la eternidad, que te hagas insustituible que no merezcas morir.
https://www.facebook.com/yasmanycurimilma
Responder