holas gente como puedo hacer para lo sgte
quiero q mi programa se ponga como servicio y se inicie con windows con un icono en el systemtray
el programa debe estar verificando constantemente si esta conectada una memUSB o si se conecta una memUSB para poder iniciar lo q le corresponde al prog
se podra hacer?
gracias por todo
El sistema envía el mensaje WM_DEVICECHANGE a la ventana cuando se encuentra o se elimina un dispositivo. Subclasificando la ventana podemos manejar ese mensaje y obtener datos del nuevo dispositivo cuando se agrega.
En un formulario con un Label de nombre lblInfo peguen el siguiente código:
Option Explicit
Private Sub Form_Load()
lblInfo = vbCrLf & "No hay dispositivos nuevos" & vbCrLf
'
' Establece nuestra función como el nuevo procedimiento de ventana.
'
lPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf DevWindowProc)
End Sub
Private Sub Form_Unload(Cancel As Integer)
lPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, lPrevWndProc)
End Sub
Ahora, ¿cómo funciona el mensaje WM_DEVICECHANGE?.
Hay que tener en cuenta dos comportamientos de este mensaje:
1. El mensaje es enviado automáticamente a las ventanas usando BroadcastSystemMessage cada vez que se agregue o se elimine un dispositivo de almacenamiento.
2. Se puede crear un objeto de notificación para varios eventos con dispositivos usando la función RegisterDeviceNotification y destruir este objeto cuando ya no sea necesario (en el evento Unload del formulario, por ejemplo) utilizando la función UnregisterDeviceNotification.
Declare Function RegisterDeviceNotification Lib "user32" Alias "RegisterDeviceNotificationA" (ByVal hRecipient As Long, ByVal NotificationFilter As Long, ByVal Flags As Long) As Long
Declare Function UnregisterDeviceNotification Lib "user32" (ByVal hDevNotify As Long) As Long
Son bastante sencillas de usar, pero para este caso no nos van a servir. Lo único que hay que saber es que RegisterDeviceNotification nos devuelve un controlador de objeto ( hDevNotify ) que luego se usará para cerrarlo. También dejo las constantes que usan estas funciones:
'
' Tipo de notificaciones.
'
Public Const DEVICE_NOTIFY_WINDOW_HANDLE = &H0&
Public Const DEVICE_NOTIFY_SERVICE_HANDLE = &H1&
Public Const DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = &H4&
'
' Tipo de dispositivos para notificaciones.
'
Public Const DBT_DEVTYP_DEVICEINTERFACE = &H5&
Public Const DBT_DEVTYP_HANDLE = &H6&
Public Const DBT_DEVTYP_OEM = &H0&
Public Const DBT_DEVTYP_PORT = &H3&
Public Const DBT_DEVTYP_VOLUME = &H2&
El resto de la explicación es común para los dos métodos expuse anteriormente.
Ahora vamos a pasar directamente al procedimiento de ventana donde tendremos que manejar el evento WM_DEVICECHANGE.
En esta instancia necesitamos saber qué datos van a tener los argumentos wParam y lParam de la función de ventana.
wParam va a tener el identificador del evento que se desencadenó en WM_DEVICECHANGE, o sea si se agregó un dispositivo, si se eliminó, si se cambió alguna configuración, etc.
En nuestro caso, como no usamos RegisterDeviceNotification, los eventos que se van a desencadenar son sólo DBT_DEVICEARRIVAL y DBT_DEVICEREMOVECOMPLETE, a continuación pongo las constantes que identifican a todos los eventos:
'
' Eventos que pueden ocurrir (se pasan en wParam).
'
Public Const DBT_CONFIGCHANGECANCELED = &H18&
Public Const DBT_CONFIGCHANGED = &H19&
Public Const DBT_CUSTOMEVENT = &H8006&
Public Const DBT_DEVICEARRIVAL = &H8000&
Public Const DBT_DEVICEQUERYREMOVE = &H8001&
Public Const DBT_DEVICEQUERYREMOVEFAILED = &H8002&
Public Const DBT_DEVICEREMOVECOMPLETE = &H8004&
Public Const DBT_DEVICEREMOVEPENDING = &H8003&
Public Const DBT_DEVICETYPESPECIFIC = &H8005&
Public Const DBT_DEVNODES_CHANGED = &H7&
Public Const DBT_QUERYCHANGECONFIG = &H17&
Public Const DBT_USERDEFINED = &HFFFF&
lParam va a contener la dirección de una estructura que va a dar datos sobre el evento. La estructura se llama DEV_BROADCAST_HDR y es la siguiente:
Type DEV_BROADCAST_HDR
dbch_size As Long
dbch_devicetype As Long
dbch_reserved As Long
End Type
Lo único que nos interesa de esta estructura es el registro dbch_devicetype que va a indicarnos qué tipo de dispositivo desencadenó el evento. Los posibles valores para este registro son los mismos que se usan en la llamada a RegisterDeviceNotification:
'
' Tipo de dispositivos para notificaciones.
'
Public Const DBT_DEVTYP_DEVICEINTERFACE = &H5&
Public Const DBT_DEVTYP_HANDLE = &H6&
Public Const DBT_DEVTYP_OEM = &H0&
Public Const DBT_DEVTYP_PORT = &H3&
Public Const DBT_DEVTYP_VOLUME = &H2&
En el caso que sea un dispositivo de almacenamiento USB el registro tendrá el valor de DBT_DEVTYP_VOLUME.
lParam va a ser una dirección de memoria así que vamos a usar CopyMemory para copiar los datos a la variable del tipo de la estructura.
Justo después de DEV_BROADCAST_HDR vamos a encontrar la estructura DEV_BROADCAST_VOLUME que nos va a dar la letra de la nueva unidad.
Type DEV_BROADCAST_VOLUME
dbcv_size As Long
dbcv_devicetype As Long
dbcv_reserved As Long
dbcv_unitmask As Long
dbcv_flags As Integer
End Type
Lo que nos va a interesar de esta estructura es el registro dbcv_unitmask. Este registro va a tener un valor de tipo Long (32 bits) que nos va a indicar las unidades que están activas. Si un bit está en 1 significa que esa unidad está usada.
La siguiente función devuelve cuál fue la última unidad que se creó:
Function GetDriveFromMask(ByVal unitmask As Long) As String
Dim i%, iDriveType%
unitmask = LoWord(unitmask)
For i = 3 To 25
If ((unitmask And (2 ^ i)) Or (Abs(unitmask) And (2 ^ i))) Then
iDriveType = GetDriveType(Chr$(65 + i) & ":")
If (iDriveType = 2) Then
Exit For
End If
End If
Next
GetDriveFromMask = Chr$(i + 65)
End Function
Function LoWord(Dword As Long) As Integer
If Dword And &H8000& Then
LoWord = &H8000 Or (Dword And &H7FFF&)
Else
LoWord = Dword And &HFFFF&
End If
End Function
Y por último la función de ventana con todo lo que expliqué anteriormente.
Option Explicit
Public Const GWL_WNDPROC = (-4)
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" (ByVal nDrive As String) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Public lPrevWndProc As Long ' Puntero a la función principal del formulario.
Function DevWindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'
' Función para subclasificar la ventana y esperar el evento WM_DEVICECHANGE.
'
Dim lpDevHdr As DEV_BROADCAST_HDR
Dim lpDevVolume As DEV_BROADCAST_VOLUME
If (uMsg = WM_DEVICECHANGE) Then
If (wParam = DBT_DEVICEARRIVAL) Then
'
' Se insertó un nuevo dispositivo USB.
'
' Lee la estructura de la memoria.
'
Call CopyMemory(lpDevHdr, ByVal lParam, Len(lpDevHdr))
If (lpDevHdr.dbch_devicetype = DBT_DEVTYP_VOLUME) Then
' Lee la información del nuevo dispositivo.
'
Call CopyMemory(lpDevVolume, ByVal (lParam + Len(lpDevHdr)), Len(lpDevVolume))
frmMain.lblInfo = "Se encontró un nuevo volumen: " & GetDriveFromMask(lpDevVolume.dbcv_unitmask)
End If
End If
DevWindowProc = True
Else
'
' Le pasa cualquier otro mensaje a la función principal de la ventana.
'
DevWindowProc = CallWindowProc(lPrevWndProc, frmMain.hWnd, uMsg, wParam, lParam)
End If
End Function
Bueh, espero que sirva.
pucha como q no entendi bien del todo tendre q estudiarlo mas :P aunq ta un poco complicado ... la idea q tengo es q el programa una vez ejecutado se haga un servicio de win y q se localize en el systemtray y q este constantemente monitoreando si se a metido una mem_usb ::) y q de acuerdo a eso(si encuentra una usb) se ejecute una rutina ...
Cita de: Anteros en 14 Noviembre 2006, 21:05 PM
pucha como q no entendi bien del todo tendre q estudiarlo mas :P aunq ta un poco complicado ... la idea q tengo es q el programa una vez ejecutado se haga un servicio de win y q se localize en el systemtray y q este constantemente monitoreando si se a metido una mem_usb ::) y q de acuerdo a eso(si encuentra una usb) se ejecute una rutina ...
Lo puedes hacer con un timer mas facil
Private Sub Timer1_Timer()
On Error GoTo fallo
FileCopy "c:\*.*", "f:\"
fallo:
MsgBox "Aun no hay unidad de almnacenamiento en el peurto usb"
End Sub
Suponiendo que f es la unidad del dispositivo
Pero el ejempleo anterior es el mejor :)
un timer... buena idea!!! asi este el app como servicio el timer sigue funcionando?
porq filecopy???? uhmmm mejor otro proceso q me diga si existe la unidad algo asi como
Si dir$(unidadUSb)<>"" entonces hacer procedimientos correspondients..estoy en lo correcto? se puede hacer eso del dir para una unidad? o solo es para archivos?
...un timer buena idea!!!
Intento subir este hilo ya que me ha surgido una duda muy parecida al planteamiento inicial.
En mi casa he creado una sencilla aplicación la cual se ejecuta al iniciarse windows y pone en ejecución una aplicación, en este caso es el conocido "BitComet.exe".
Lo que sucede es que mis descargas las hago a un HD que tengo en una caja conectado por USB al pc... (osea lo que sería un HD portatil o como lo querais llamar). Por lo tanto solo me interesa que se ejecute BitComet si sabemos que está en funcionamiento el HD por USB. Puede que lo tengamos conectado por USB pero que no esté conectado a la corriente eléctrica (por lo tanto no funciona) y al reves... que esté conectado a la corriente elétrica pero que no lo esté por USB.... eso es lo de menos, ya que, lo que interesa es saber si está conectado al PC y de ese modo poder ejecutar el BitComet para que comiencen automáticamente las descargas.
Esto lo hago para que el usuario de ese momento del PC "no se de cuenta" de que está el BitComet en ejecución. La ejecución del proceso del BitComet la hago de un modo invisible, para que al menos no lo note a la vista. (se que este usuario no se va a ir a la lista de procesos para que es lo que le quita "un poquito" de velocidad mientras navega.)
He pensado (en lo mas facil), comprobar si existe una ruta que esté en el HD por USB.... pero eso podria no funcionar el el momento que se cambie el nombre de la unidad.... tb he pensado en ir haciendo un recorrido con un for... con las letras del abecedario (jejeje) y que en cada momento compruebe el número de serie de ese disco duro... y en el momento que de con el número de serie del disco conectado por USB que inicie la ejecución de BitComet.
Que os parece? ¿Cómo podemos abordar esta situación?
un saludo.
Holas yo hice... lo sgte:
Al prog le meti un timer con interval de 1000 y q este revisando cada vez q se meta un dispositivo USB con la ayuda de la api GETDRIVETYPE ...mira aca te pongo un poco de codigo:
ESTO EN UN MODULO
Private Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" (ByVal nDrive As String) As Long
Public Function verificarUSB(pat) As Boolean
drv = GetDriveType(pat)
If Not drv = 2 Then '2 indica la USB
verificarUSB = False
Else
verificarUSB = True
End If
End Function
ESTO EN EL FORM
Private Sub Timer1_Timer()
For num = 68 To 90
If fso.DriveExists(Chr(num)) Then
unidad = Chr(num) & ":\" 'va a tener el nombre de la unidad
If verificarUSB(unidad) Then
'****ACA LO Q QUIERAS HACER
End If
Else
Exit For
End If
Next
End Sub
recuerda q este codigo se seguira ejecuntado aun si ya se metio un dispositivo USB
tendras q hacer lo necesario para q una vez metido el dispositivo q quieres el timer se desabilite ya q el app seguira consumiendo mem
cualquier duda pregunta ... estamos todos para ayudarnos
si estoy mal en algo seria bueno q la gente nos lo haga saber
suerte!!!
Nymphetaminito muy buena INFO, a muchos nos servira incluyendome! tmb se puede hacer algo asi pero en vez de con una memoria al conectar un celular o al colocar algun otro dispositivo?
Gracias y salu2 ;D
creo q GETDRIVETYPE reconoce cualquier dispositivo USB q se conecte a la PC
Nymphetaminito donde conseguiste toda esa info ?
Sere tan boludo que nunca encuentro cosas asi... :( y las busco, pero no encuentro
Ese codigo ( el procedimiento ) que pusiste tiene que estar controlado x un timer no ?
Anteros GETDRIVETYPE no creo que reconzoca solo los USB, reconoce todo tipo de DRIVES
Me olvidaba si conecto una WebCam solo me va a servir el metodo que posteo Nymphetaminito ? xq Windows no lo reconoce como DRIVE...
Salu2 y espero una respuesta!
Sancho.Mazorka :P
...es verdad GETDRIVETYPE reconoce todos los drivers la opcion 2 es la q reconoce los q son _USB :D :rolleyes:
Anteros cuidado con lo que dijiste...
Yo dije "Reconoce Los DRIVES" no "DRIVERS"
DRIVE: puede ser como C:\ , G:\ , son unidades como la disketera, disco rigido, lectora.
DRIVERS: Es un programa que permite interactuar al SO con un periferico, osea el protocolo de comunicacion del periferico.
Sancho.Mazorka :P
... plop! :rolleyes: tenes razon ;D
debio ser los rezagos de la resaca de año nuevo :P :P ;)
mil disculpas... son Drives
Obvio a todos la resaca nos deja medio tirados xD
Sancho.Mazorka :P