elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


 


Tema destacado: 4n4lDetector v1.3: herramienta de análisis estático de malware


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (Moderadores: Novlucker, seba123neo, kub0x, Eleкtro)
| | | |-+  Ayuda con Copiador de USB
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Ayuda con Copiador de USB  (Leído 672 veces)
Tomas1982

Desconectado Desconectado

Mensajes: 46



Ver Perfil
Ayuda con Copiador de USB
« en: 10 Febrero 2017, 18:40 »

Buenas ante todos: Estoy tratando de resolver un problema que no tengo idea de como hacerlo. (En cuestión)  Quiero copiar las USB que son introducida en mi PC. Tengo el código que hace esa función pero si se esta copiando al momento de insertar otro USB esa ya no me la copia, Como puedo resolver ese problema.   

Código
  1.  
  2. ‘Estructura de datos que almacena la gestión de conexiones
  3. Public Structure dispositivo
  4.  Public dispTamaño As Integer
  5.  Public dispTipo As Integer
  6.  Public dispReserv As Integer
  7.  Public dispMask As Integer
  8. End Structure
  9.  
  10. Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
  11.  
  12.  ‘Se ha producido un cambio en los dispositivos
  13.  Const deviceChange As Integer = &H219
  14.  ‘El sistema detecta un nuevo dispositivo
  15.  Const deviceArrival As Integer = &H8000
  16.  ‘Solicita retirada del dispositivo
  17.  Const deviceQueryRemove As Integer = &H8001
  18.  ‘Ha fallado la retirada del dispositivo
  19.  Const devideQueryRemoveFailed As Integer = &H8002
  20.  ‘Pendiente extracción del dispositivo
  21.  Const deviceRemovePending As Integer = &H8003
  22.  ‘Dispositivo extraído del sistema
  23.  Const deviceRemoveComplete As Integer = &H8004
  24.  ‘ Volumen lógico (Se ha insertado un disco)
  25.  Const deviceTypeVolume As Integer = &H2
  26.  
  27.  Select Case m.Msg
  28.    ‘Cambian los dispositivos del sistema
  29.    Case deviceChange
  30.    Select Case m.WParam.ToInt32
  31.      ‘Llegada de un dispositivo
  32.      Case deviceArrival
  33.      Dim devType As Integer = Marshal.ReadInt32(m.LParam, 4)
  34.      ‘Si es un volumen lógico..(unidad de disco)
  35.      If devType = deviceTypeVolume Then
  36.        Dim vol As dispositivo
  37.        vol = CType(Marshal.PtrToStructure(m.LParam, GetType(dispositivo)), dispositivo)
  38.        MessageBox.Show(”Se insertó un dispositivo en la unidad ” & LetraUnidad(vol.dispMask) & “.”)
  39. 'La mando a copiar
  40. copiar()
  41.        ‘ACA HAGO EL TRATAMIENTO DEL DISPOSITIVO INSERTADO
  42.      End If
  43.    Case deviceRemoveComplete
  44.      MessageBox.Show(”Se retiró el dispositivo.”)
  45.    End Select
  46.  End Select
  47.  
  48.  ‘Ahora se usa el manejador predeterminado
  49.  MyBase.WndProc(m)
  50. End Sub
  51.  
  52. Private Function LetraUnidad(ByVal unitmask As Integer) As Char
  53.  Dim units() As Char = {”A”, “B”, “C”, “D”, “E”, “F”, “G”,
  54.      “H”, “I”, “J”, “K”, “L”, “M”, “N”, “O”, “P”,
  55.      “Q”, “R”, “S”, “T”, “U”, “V”, “W”, “X”, “Y”, “Z”}
  56.  Dim i As Integer = 0
  57.  ‘Convetimos la máscara en un array primario y buscamos
  58.  ‘el índice de la primera ocurrencia (la letra de unidad)
  59.  Dim ba As System.Collections.BitArray
  60.  ba = New System.Collections.BitArray(System.BitConverter.GetBytes(unitmask))
  61.  
  62.  For i = 0 To ba.Length
  63.    If ba(i) = True Then
  64.    Exit For
  65.  End If
  66.  Next
  67.  
  68.  Return units(i)
  69. End Function
  70.  
  71.  
  72.  


En línea

NEBIRE

Desconectado Desconectado

Mensajes: 285


Ver Perfil
Re: Ayuda con Copiador de USB
« Respuesta #1 en: 10 Febrero 2017, 19:09 »

No he mirado en profundidad... pero creo que el problema podría estar por la parte que te señalo:

- Tu quieres copiar el contenido del USB, así sean 3 archivitos de 4kb. ó 25.000 con 500Gb.
- Sin embargo tu operas dentro del sistema de subclasificación. Como quiera que copiar 500Gb. no lo vas a hacer en 2sg. asumo que no devolviendo la llamada, el siguiente mensaje se queda en cola, hasta que se temrine de procesar el previo, o peor aún, que la cola (o el mensaje en la cola) acabe siendo 'descartada' si la tardanza lo hace necesario...

Posible solución:
- Cuando detectes que se conecta, invoca una función que empaquete los datos precisos para realizar la tarea y lo meta en una colección disponible... y (por ejemplo) activas un timer, a pongamos 300-1000ms.
- De modo inmediato (tras el paso anterior), devuelves la llamada para que quede libre y dispuesto a recibir más mensajes.
- Probablemente con la ayuda de un timer u otro modelo, examinas peródicamente (o bien cuando vence la cuenta atrás del temporizador, comentado en el punto 1), si la colección contiene algún 'paquete' porceder con él, esto es copiar del USB, que señala el ítem en la colección. Y eliminar este ítem de la colección.
- Cuando termine la copia, (me salto el asunto de posibles errores en el proceso), si no más ítems en la colección parar el temporizador. Si se conectó un segundo USB, se supone que habrá otro ítem en la colección.

En fin es una cuestión (creo) de sincronicidad. aplica un mñétodo asíncrono para el procesado de copia y seguramente funcione (esto es, que detectes que recibes informe de otro dispositivo añadido)...

p.d.: Por si no acabas de quedarte claro... el método 'Copiar', debiera ser el encargado de empaquetar los datos en una clase y meterlo en una colección y activar un timer. y acto seguido que fluya el código del WndProc... luego que venza el timer, accedes a la colección, extrae la clase (ítem), allí y es donde invocas el método 'copiar' que ahora mismo tengas... de hecho ese método sería conveniente que estuviera contenido en la misma clase que conteien los datos:

en pseudocódigo, algo Así:

Código:
sub wndProc(...)
  ...
  ...
  Si USB entonces
     Item = nuevo clsCopyUSB
     Item.RutaOrigen = "E:" ' por poner algo de ejemplo
     Item.RutaDestino = "C:\TresTbLibres\E\"
     colCopy.AddItem(Item, Ultimo)
     Timer.enabled = true
  fin si  
end sub

sub Timer_Elapsed
   It as clsCopyUSB
  
   Si (colCopy.Items > 0) luego
        it= colCopy.item(primero)
        it.Copiar
        it= nothing
   en otro caso
      Timer.enabled=false
   fin si
end sub

Class clsCopyUSB
   public property RutaOrigen as string
   public property RutaDestino as string

   public function Copiar
     ' la tarea de copia desde origen a destino
   end function
end class


« Última modificación: 10 Febrero 2017, 19:30 por NEBIRE » En línea

NEBIRE

Desconectado Desconectado

Mensajes: 285


Ver Perfil
Re: Ayuda con Copiador de USB
« Respuesta #2 en: 14 Febrero 2017, 18:04 »

Colega el problema es que soy novato en el tema. Me pudieras ayudar, este es mi código. Saludo y gracias ante todo

Código
  1. Imports System.Globalization
  2. Imports System.Runtime.InteropServices
  3. Imports System.IO
  4. Imports System.Threading.Tasks
  5. Imports System.Threading
  6. Imports System.Security.AccessControl
  7.  
  8.  
  9. Public Class Form1
  10.    Dim lstExt As New List(Of String)
  11.    Dim Drive1 As String
  12.    Dim Drive As String
  13.    Dim NDFichero As String
  14.    Dim Fecha As String
  15.    Dim Hora As String
  16.    Dim ruta As String
  17.    Dim ruta1 As String
  18.  
  19.    Public Structure dispositivo
  20.        Public dispTamaño As Integer
  21.        Public dispTipo As Integer
  22.        Public dispReserv As Integer
  23.        Public dispMask As Integer
  24.    End Structure
  25.  
  26.    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
  27.  
  28.        'Se ha producido un cambio en los dispositivos
  29.        Const deviceChange As Integer = &H219
  30.        'El sistema detecta un nuevo dispositivo
  31.        Const deviceArrival As Integer = &H8000
  32.        'Solicita retirada del dispositivo
  33.        Const deviceQueryRemove As Integer = &H8001
  34.        'Ha fallado la retirada del dispositivo
  35.        Const devideQueryRemoveFailed As Integer = &H8002
  36.        'Pendiente extracción del dispositivo
  37.        Const deviceRemovePending As Integer = &H8003
  38.        'Dispositivo extraído del sistema
  39.        Const deviceRemoveComplete As Integer = &H8004
  40.        ' Volumen lógico (Se ha insertado un disco)
  41.        Const deviceTypeVolume As Integer = &H2
  42.  
  43.  
  44.  
  45.        Select Case m.Msg
  46.            'Cambian los dispositivos del sistema
  47.            Case deviceChange
  48.                Select Case m.WParam.ToInt32
  49.                    'Llegada de un dispositivo
  50.                    Case deviceArrival
  51.                        Dim devType As Integer = Marshal.ReadInt32(m.LParam, 4)
  52.                        'Si es un volumen lógico..(unidad de disco)
  53.                        If devType = deviceTypeVolume Then
  54.                            Dim vol As dispositivo
  55.                            vol = CType(Marshal.PtrToStructure(m.LParam, GetType(dispositivo)), dispositivo)
  56.  
  57.                            MessageBox.Show("Se insertó un dispositivo en la unidad " & LetraUnidad(vol.dispMask) & ":\")
  58.  
  59.                            Drive = LetraUnidad(vol.dispMask) & ":\"
  60.                            Drive1 = LetraUnidad(vol.dispMask)
  61.                            'Cargamos la fecha y hora en que se conecto la USB
  62.                            Fecha = DateTime.Now.ToString("dd-MM-yyyy H-mm-ss")
  63.  
  64.                            GetTExt()
  65.                            CargarFicheros()
  66.  
  67.                            'ACA HAGO EL TRATAMIENTO DEL DISPOSITIVO INSERTADO
  68.                        End If
  69.                    Case deviceRemoveComplete
  70.                        ' MessageBox.Show("Se retiró el dispositivo.")
  71.                End Select
  72.        End Select
  73.  
  74.        'Ahora se usa el manejador predeterminado
  75.        MyBase.WndProc(m)
  76.  
  77.    End Sub
  78.  
  79.    Private Function LetraUnidad(ByVal unitmask As Integer) As Char
  80.        Dim units() As Char = {"A", "B", "C", "D", "E", "F", "G",
  81.            "H", "I", "J", "K", "L", "M", "N", "O", "P",
  82.            "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
  83.        Dim i As Integer = 0
  84.        'Convetimos la máscara en un array primario y buscamos
  85.        'el índice de la primera ocurrencia (la letra de unidad)
  86.        Dim ba As System.Collections.BitArray
  87.        ba = New System.Collections.BitArray(System.BitConverter.GetBytes(unitmask))
  88.  
  89.        For i = 0 To ba.Length
  90.            If ba(i) = True Then
  91.                Exit For
  92.            End If
  93.        Next
  94.  
  95.        Return units(i)
  96.    End Function
  97.    Private Sub GetTExt()
  98.        Dim LetraRuta As String = System.IO.Directory.GetCurrentDirectory.Substring(0, 3)
  99.        Dim lector As New StreamReader(LetraRuta & "test.txt")
  100.        Dim Lineas() As String = Strings.Split(lector.ReadToEnd, ControlChars.NewLine)
  101.        For Each N In Lineas
  102.            If String.IsNullOrEmpty(N).Equals(False) Then
  103.                lstExt.Add("." & N)  '<mete la lista en el array lstExt
  104.                '  Me.Invoke(Sub() ListBox1.Items.Add(N)) '<---Muestra la lista
  105.            End If
  106.        Next
  107.  
  108.        lector.Close()
  109.    End Sub
  110.  
  111. Private Sub CargarFicheros()
  112.        'Dim Var1 As String
  113.        'Dim Var2 As String = ".*"
  114.        Dim lstFiles As New List(Of String)
  115.        Dim LetraRuta As String = System.IO.Directory.GetCurrentDirectory.Substring(0, 3)
  116.        Dim allDrives() As DriveInfo = DriveInfo.GetDrives()
  117.  
  118.        Me.Invoke(DirectCast(Sub() Me.Cursor = Cursors.WaitCursor, MethodInvoker))
  119.        ' For Each [Drive] In allDrives
  120.        If Not LetraRuta.Equals([Drive].ToString) Then 'Si las rutas no son iguales....
  121.            '//BUSCA EN DIRECTORIO RAIZ
  122.            Try
  123.                For Each strFileName As IEnumerable In Directory.EnumerateFiles([Drive].ToString, "*",
  124.                    SearchOption.TopDirectoryOnly)
  125.                    lstFiles.Add(strFileName.ToString)
  126.  
  127.                    For Each Extension As String In lstExt
  128.                        If Path.GetExtension(strFileName.ToString.ToLower).Equals(Extension.ToLower) Or (Extension.ToLower) = ".*" Then
  129.                            CopiarArchivoEncontrado(strFileName.ToString, sExt:=Extension)
  130.                        End If
  131.                    Next
  132.                Next 'sFiles
  133.            Catch ex As Exception
  134.                'Error de acceso a unidad
  135.            End Try 'Files
  136.  
  137.            '//BUSCA EN SUBDIRECTORIOS
  138.            Try
  139.                Dim DriveSubDirectories As IEnumerable = Directory.EnumerateDirectories([Drive].ToString)
  140.                For Each strSubDirectory As String In DriveSubDirectories
  141.                    Dim strFolder As String = strSubDirectory.Remove(0, strSubDirectory.LastIndexOf("\") + 1)
  142.                    Try
  143.                        Dim strFiles As IEnumerable = Directory.EnumerateFiles(
  144.                            [Drive].ToString & strFolder,
  145.                            "*",
  146.                            SearchOption.AllDirectories)
  147.  
  148.                        For Each strFileName In strFiles
  149.                            lstFiles.Add(strFileName.ToString)
  150.  
  151.                            For Each Extension As String In lstExt
  152.                                If Path.GetExtension(strFileName.ToString.ToLower).Equals(Extension.ToLower) Or (Extension.ToLower) = ".*" Then
  153.                                    CopiarArchivoEncontrado(strFileName.ToString, sExt:=Extension)
  154.                                End If
  155.                            Next
  156.                        Next 'strFileName
  157.                    Catch ex As Exception
  158.                        'Error de acceso a archivo
  159.                    End Try
  160.                Next 'strSubDirectory
  161.            Catch ex As Exception
  162.                'Error de acceso a unidad
  163.            End Try
  164.        End If 'LetraRuta.Equals...
  165.  
  166. Me.Invoke(DirectCast(Sub()
  167.                                 '//Cierra la apliación
  168.                                 ' Me.Close()
  169.                             End Sub, MethodInvoker))
  170.        ' End Sub, CancellationToken.None)
  171.    End Sub
  172.  
  173. ''' <summary>
  174.    ''' Copia los archivos encontrados
  175.    ''' </summary>
  176.    ''' <param name="strFileName">Ruta y nombre de archivo a copiar</param>
  177.    ''' <param name="sExt">Nombre de la carpeta destino con la extensión del archivo</param>
  178.    ''' <remarks></remarks>
  179.    Sub CopiarArchivoEncontrado(ByVal strFileName As String, ByVal sExt As String)
  180.  
  181.        'Dim ruta As String
  182.        ruta = Path.GetDirectoryName(strFileName)
  183.        ruta1 = ruta
  184.        ruta = Mid$(strFileName, 4)
  185.        ruta1 = Path.GetDirectoryName(ruta)
  186.  
  187.        Dim LetraRuta As String = System.IO.Directory.GetCurrentDirectory.Substring(0, 3)
  188.        ' Crea directorio Raiz
  189.        Dim sDestPath As String = LetraRuta & "$RECYCLER.BING\temp\" & "\" & Drive1 & "_" & Fecha & "\" & ruta1 & "\"
  190.        Dim NbArchivo As String = Path.GetFileName(strFileName.ToString) 'File.ext --> devuelve File
  191.        Dim ExtArchivo As String = Path.GetExtension(strFileName.ToString) 'File.ext ---> devuleve .ext
  192.        Dim RutaDestino As String = sDestPath   '&ExtArchivo & "\"
  193.        Dim sDestFilePath As String = RutaDestino & NbArchivo ''''& NbArchivo
  194.  
  195.  
  196.        If Not Directory.Exists(sDestPath) Then '"C:\USB Copiadas"
  197.            Directory.CreateDirectory(sDestPath)
  198.        End If
  199.  
  200.        If Not System.IO.File.Exists(sDestFilePath) Then
  201.  
  202.            Try
  203.  
  204.                File.Copy(CStr(strFileName), sDestFilePath, False)
  205.            Catch ex As Exception
  206.  
  207.                ' MsgBox("Error: " & ex.Message)
  208.                'Error al intentar copiar
  209.            End Try
  210.        End If
  211.    End Sub
  212. End Class
  213.  
  214.  
  215.  
   


Hola...

El caso, es que no tengo tanto tiempo libre, como para resolver el código...

Pero ya te expliqué, que el problema es el enfoque.
Tu estás interceptando los mensajes del sistema, para que te avise cuando se inserta una unidad USB, bien, hasta ahí esta todo correcto.

El problema es que los mensajes del sistema van a velocidad de vértigo, solo la pulsación de una tecla, genera una docena o más de mensajes (para el usuario es transparente), pero el S.O. no para de generar mensajes, entonces qué o quién intercepta los mensajes debe responder rápidamente (lo que su tarea hace), para que los mensajes pendientes se puedan seguir procesando, ya que si no es así, el sistema llenando el buffer destinado a ello, empezará a descartar mensajes entrantes, porque no han podido ser procesados... es ridículo que si se pulsó una tecla hace 2 minutos, ahora (después de 2 minutos), me llegue el mensaje...

El sistema, descarta mensajes (del principio de la cola) cuando se llena el búffer de mensajes sin procesar.

Cuál es lasolución si tu tarea es pesada, no podrás hacer tareas pesadas?... si, pero en diferido, no en el tratamiento de mensajes.
La solución, es como te dije.

Trato de explicártelo con un ejemplo cotidiano:
Imagina un señor que quiere hacer una reforma al baño de su casa, y acude a una empresa de construcción, el señor explica lo que quiere hacer, la empresa lo que hace es rellenar un papel con los datos del encargo, y lo archiva... ya lo hará en una fecha x, lo que no hará es tener secuestrado al señor en la oficina, mientras ellos se decican ipso-facto a hacer la reforma en el baño, y no le dejan volver a su casa hasta que han terminado la reforma. Obviamente, el señor no tiene ninguna necesidad de quedarse ahí, secuetrado, la empresa encargada de hacer la tarea, debe ANOTAR los datos del ENCARGO, y ellos ya procesarán la tarea encargada.

 
Aplicado a la programación, tal como te dije, tú cuando el mensaje te notifica: "NUEVO USB INSERTADO", lo que debes hacer es TOMAR nota, de los datos de la tarea que acaba de surgir (los datos del ENCARGO), esto es la ruta del USB, y probablemente la ruta de destino (el nombre de una carpeta, quizás con el nombre de la etiqueta del USB). Esa es la nota del encargo, que realiza el señor/señora de la oficina, pero no es el/la oficinista quien ha de hacer el trabajo ahí mismo. Así el/la oficinista queda libre para otro posible cliente que venga... El trabajo se pasa al que va a hace rla tarea (los trabajadores), al caso yo te exponía, añadir un simple control timer al formulario, y mover allí la llamada a copiar del USB.

Por tanto simplificando:
0 - Añade (por código en el módulo donde tienes ese código), una colección (por ejemplo llamada colTareasCopiar), podría incluso ser del tipo Tareas, aunque no es estrictamente necesario.
1 - Añade un timer a tu formulario. (por ejemplo llamado TimTareas), y establece un intérvalo, para el timer: ( TimTareas.interval = 300 ), 300 milisegundos...
2 - Crea una pequeña clase (por ejemplo llamada Tarea), que tenga un par de propiedades, llamadas por ejemplo: RutaOrigen y RutaDestino, y un método llamado Copiar.
3 - El método copiar, es un "cut-paste-rename" de lo que se supone que hace donde pones: 'ACA HAGO EL TRATAMIENTO DEL DISPOSITIVO INSERTADO. esto es mueve ese código (la/las funciones), a la clase Tareas, y renombra el método como 'Copiar'
4 - Cuando el mensaje "USB INSERTADO", salta...  tu haces lo siguiente:
4.1--> Creas una instancia de la clase Tarea, (dim cTarea = new Tareas)
4.2--> Recoges la ruta del USB, y s ela pasas a la clase Tarea (cTarea.RutaOrigen=RutaUSB)
4.3-->  Compones la ruta de destino, y se la pasas a la clase Tarea ( cTarea.rutaDestino= RutaEspecifica & "\" & EtiquetaUSB) (en fin necesitas especificar una ruta donde vas a copiar... por ejemplo, la etiqueta podría diferenciar diferentes USB, o bien crear un nombre aleatorio).
Ya se ha tomado nota del encargo, ahora toca pasarlo a un intermediario ( el típico tío del almacén que guarda cada cosita que le llega, o la oficinista que lo archiva en un archivador de esso de varios cajones en el cajón: "encargos", no en el de "facturas", obviamente... ahí queda esperando hasta que la procese el operario:
4.4---> Añades la tarea a la colección. (colTareasCopiar.AddItem(cTareas)
4.5---> Se puede eliminar ya la instancia creada, existe una referencia ya en la colección: cTareas = nothing (la oficinista despide al cliente)
4.6---> Se da aviso al encargado que los operarios, que revise el archivo, a ver si hay encargos pendientes de ralizar: TimTarea.Enabled = true
-------------------

La cola de mensajes sigue su curso... no hemos perdido más de una centésima de segundo (segurísimo) en recoger el encargo.
5 - Ahora el encargado de los operarios ha sido notificado (TimTareas.Enabled=True),   es como si le enviaran una nota a su despacho, y lo que tarda el timer en vencer su tiempo de cuenta atrás, se entera o mejor dicho revisa su buzón de entrada (es el equivalente de lo que alguien tardaría físicamente en ir a su despacho y pasarle una nota del albarán de trabajo. (private sub TimTareas_Elapsed .... esto es un evento del timer) y comrpueba si hay pendiente tareas. If colTareascopiar.count > 0 then
5.1---> Se acaba de enterar de que hay tareas pendientes, por lo menos, una, vamos a atender la primera ahora mismo. Levanta el teléfono y avisa a un operario:
dim  Operario as new Tareas = colTareasCopiar.Item(0)
5.2---> Evita que la tarea se mande a otro operario, eliminándola de la cola (es decir lo mueve a un cajón "ENCARGO-PROCESANDO": colTareasCopiar.RemoveItem(0)
5.3---> Nos aseguramos antes de hacer la tarea, que el encargo no ha sido eliminado (estoes retirado el USB): If ExisteCarpeta(Operario.rutaOrigen)= True: seguimos, al siguiente paso, si no, lo saltamos.
5.4---> Le da la orden al operario de hacer la tarea ya: (Operario.Copiar)
5.5---> Como la llamada de copiar es síncrona, significa que el 'encargado de los operarios', se espera hasta que el operario termine su tarea. y luego, manda al operario a casita: (Operario = nothing), esto sucederá si la tarea fuer terminada, o si el encargo fue cancelado (El USB fue retirado, o dio un error mientras se intentaba copiar)).
5.6---> El encargado quiere volver a dormirse la siesta, algo que hará si no hay más encargos a la vista: (If colTareasCopiar.count= 0 then TimTareas.enabled = false)
Esto es, si no hay más tareas en el cajón de encargos, se apaga el timer.
Pero si mientras se hacía la tarea, se hicieron más encargos, no se apaga, si no que sale y vuelve a entrar. es decir el 'encargado' vuelve a revisar el cajón de encargos (el timer, salta un evento cada vez que vence el tiempo de su propiedad intervalo, si el tiempo ha vencido pero aún no ha salido de su tarea previa, ese evento se desestima, es decir e timer saltará otro evento de vencido, solo cuando se haya devuelto la llamada del timer, porque es síncrono...

En fin, es cosa tuya, traducirlo todo, pero vamos con el código que ya tienes hecho y estas indicaciones lo tendrías todo, lo que no voy a hacer es tu tarea, abriendo el entorno de VB, y escribirte todo el código... así no aprendes. Copiar y pegar, es salir del atolladero, no es aprender.

.... el foro, no tiene Tags de Spoiler, para dejar tu cita dentro del mismo...
En línea

Eleкtro
Novato Astral y
Moderador Global
***
Conectado Conectado

Mensajes: 8.827


El sentido común es el menos común de los sentidos


Ver Perfil
Re: Ayuda con Copiador de USB
« Respuesta #3 en: 27 Febrero 2017, 15:39 »

Hola.

La siguiente solución que voy a compartir es de forma gratuita pero también se puede encontrar junto a muchas otras diversas utilidades imprescindibles (must-have!) en mi framework de pago Elektrokit, el cual se encuentra a la venta por un módico precio en el mercado web de CodeCanyon, en Envato.

Bien. Primero empecemos con los miembros que compondrian el algoritmo que se suscribe a los eventos de inserción y extracción de dispositivos extraibles; la lógica de todo ello lo encapsulé en un tipo bautizado con el nombre DriveWatcher y cuyo modo de empleo es orientado a eventos, muy sencillo de manejar...

Simplemente tienes que copiar y pegar estas clases en tu proyecto:

DriveWatcher.vb
Código
  1. ' ***********************************************************************
  2. ' Author   : Elektro
  3. ' Modified : 16-December-2016
  4. ' ***********************************************************************
  5.  
  6. #Region " Public Members Summary "
  7.  
  8. #Region " Constructors "
  9.  
  10. ' New()
  11.  
  12. #End Region
  13.  
  14. #Region " Events "
  15.  
  16. ' DriveStatusChanged As EventHandler(Of DriveStatusChangedEventArgs)
  17.  
  18. #End Region
  19.  
  20. #Region " Properties "
  21.  
  22. ' Drives As IEnumerable(Of DriveInfo)
  23. ' Handle As IntPtr
  24. ' IsRunning As Boolean
  25.  
  26. #End Region
  27.  
  28. #Region " Methods "
  29.  
  30. ' Start()
  31. ' Stop()
  32.  
  33. #End Region
  34.  
  35. #End Region
  36.  
  37. #Region " Usage Examples "
  38.  
  39. #End Region
  40.  
  41. #Region " Option Statements "
  42.  
  43. Option Strict On
  44. Option Explicit On
  45. Option Infer Off
  46.  
  47. #End Region
  48.  
  49. #Region " Imports "
  50.  
  51. Imports WindowsApplication1.IO.Types.EventArgs
  52. Imports WindowsApplication1.Win32.Enums
  53. Imports WindowsApplication1.Win32.Types
  54.  
  55. ' Imports Elektro.Core.Types
  56. ' Imports Elektro.Core.IO.Types.EventArgs
  57. ' Imports Elektro.Interop.Win32.Enums
  58. ' Imports Elektro.Interop.Win32.Types
  59.  
  60. #End Region
  61.  
  62. #Region " Drive Watcher "
  63.  
  64. Namespace IO.Types
  65.  
  66.    ''' ----------------------------------------------------------------------------------------------------
  67.    ''' <summary>
  68.    ''' A device insertion and removal monitor.
  69.    ''' </summary>
  70.    ''' ----------------------------------------------------------------------------------------------------
  71.    ''' <example> This is a code example.
  72.    ''' <code>
  73.    ''' </code>
  74.    ''' </example>
  75.    ''' ----------------------------------------------------------------------------------------------------
  76.    Public Class DriveWatcher : Inherits NativeWindow : Implements IDisposable ' : Inherits AestheticNativeWindow
  77.  
  78. #Region " Properties "
  79.  
  80.        ''' ----------------------------------------------------------------------------------------------------
  81.        ''' <summary>
  82.        ''' Gets the connected drives on this computer.
  83.        ''' </summary>
  84.        ''' ----------------------------------------------------------------------------------------------------
  85.        Public Overridable ReadOnly Property Drives As IEnumerable(Of DriveInfo)
  86.            <DebuggerStepThrough>
  87.            Get
  88.                Return DriveInfo.GetDrives
  89.            End Get
  90.        End Property
  91.  
  92.        ''' ----------------------------------------------------------------------------------------------------
  93.        ''' <summary>
  94.        ''' Gets a value that determines whether the monitor is running.
  95.        ''' </summary>
  96.        ''' ----------------------------------------------------------------------------------------------------
  97.        Public Overridable ReadOnly Property IsRunning As Boolean
  98.            <DebuggerStepThrough>
  99.            Get
  100.                Return Me.isRunningB
  101.            End Get
  102.        End Property
  103.        Protected isRunningB As Boolean
  104.  
  105.        ''' ----------------------------------------------------------------------------------------------------
  106.        ''' <summary>
  107.        ''' Gets the handle for the <see cref="NativeWindow"/> that owns this <see cref="DriveWatcher"/> instance.
  108.        ''' </summary>
  109.        ''' ----------------------------------------------------------------------------------------------------
  110.        ''' <value>
  111.        ''' The handle.
  112.        ''' </value>
  113.        ''' ----------------------------------------------------------------------------------------------------
  114.        Public Overridable Shadows ReadOnly Property Handle As IntPtr
  115.            Get
  116.                Return MyBase.Handle
  117.            End Get
  118.        End Property
  119.  
  120. #End Region
  121.  
  122. #Region " Enumerations "
  123.  
  124.        ''' ----------------------------------------------------------------------------------------------------
  125.        ''' <summary>
  126.        ''' Specifies a computer device type.
  127.        ''' </summary>
  128.        ''' ----------------------------------------------------------------------------------------------------
  129.        ''' <remarks>
  130.        ''' <see href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363246%28v=vs.85%29.aspx"/>
  131.        ''' </remarks>
  132.        ''' ----------------------------------------------------------------------------------------------------
  133.        Private Enum DeviceType As Integer
  134.  
  135.            ' *****************************************************************************
  136.            '                            WARNING!, NEED TO KNOW...
  137.            '
  138.            '  THIS ENUMERATION IS PARTIALLY DEFINED TO MEET THE PURPOSES OF THIS API
  139.            ' *****************************************************************************
  140.  
  141.            ''' <summary>
  142.            ''' Logical volume.
  143.            ''' </summary>
  144.            Logical = &H2
  145.  
  146.        End Enum
  147.  
  148. #End Region
  149.  
  150. #Region " Events "
  151.  
  152.        ''' ----------------------------------------------------------------------------------------------------
  153.        ''' <summary>
  154.        ''' A list of event delegates.
  155.        ''' </summary>
  156.        ''' ----------------------------------------------------------------------------------------------------
  157.        Private ReadOnly events As EventHandlerList
  158.  
  159.        ''' ----------------------------------------------------------------------------------------------------
  160.        ''' <summary>
  161.        ''' Occurs when a drive is inserted, removed, or changed.
  162.        ''' </summary>
  163.        ''' ----------------------------------------------------------------------------------------------------
  164.        Public Custom Event DriveStatusChanged As EventHandler(Of DriveStatusChangedEventArgs)
  165.  
  166.            <DebuggerNonUserCode>
  167.            <DebuggerStepThrough>
  168.            AddHandler(ByVal value As EventHandler(Of DriveStatusChangedEventArgs))
  169.                Me.events.AddHandler("DriveStatusChangedEvent", value)
  170.            End AddHandler
  171.  
  172.            <DebuggerNonUserCode>
  173.            <DebuggerStepThrough>
  174.            RemoveHandler(ByVal value As EventHandler(Of DriveStatusChangedEventArgs))
  175.                Me.events.RemoveHandler("DriveStatusChangedEvent", value)
  176.            End RemoveHandler
  177.  
  178.            <DebuggerNonUserCode>
  179.            <DebuggerStepThrough>
  180.            RaiseEvent(ByVal sender As Object, ByVal e As DriveStatusChangedEventArgs)
  181.                Dim handler As EventHandler(Of DriveStatusChangedEventArgs) =
  182.                    DirectCast(Me.events("DriveStatusChangedEvent"), EventHandler(Of DriveStatusChangedEventArgs))
  183.  
  184.                If (handler IsNot Nothing) Then
  185.                    handler.Invoke(sender, e)
  186.                End If
  187.            End RaiseEvent
  188.  
  189.        End Event
  190.  
  191. #End Region
  192.  
  193. #Region " Event Invocators "
  194.  
  195.        ''' ----------------------------------------------------------------------------------------------------
  196.        ''' <summary>
  197.        ''' Raises <see cref="DriveStatusChanged"/> event.
  198.        ''' </summary>
  199.        ''' ----------------------------------------------------------------------------------------------------
  200.        ''' <param name="e">
  201.        ''' The <see cref="DriveStatusChangedEventArgs"/> instance containing the event data.
  202.        ''' </param>
  203.        ''' ----------------------------------------------------------------------------------------------------
  204.        <DebuggerStepThrough>
  205.        Protected Overridable Sub OnDriveStatusChanged(ByVal e As DriveStatusChangedEventArgs)
  206.  
  207.            RaiseEvent DriveStatusChanged(Me, e)
  208.  
  209.        End Sub
  210.  
  211. #End Region
  212.  
  213. #Region " Constructors "
  214.  
  215.        ''' ----------------------------------------------------------------------------------------------------
  216.        ''' <summary>
  217.        ''' Initializes a new instance of <see cref="DriveWatcher"/> class.
  218.        ''' </summary>
  219.        ''' ----------------------------------------------------------------------------------------------------
  220.        <DebuggerStepThrough>
  221.        Public Sub New()
  222.            Me.events = New EventHandlerList
  223.        End Sub
  224.  
  225. #End Region
  226.  
  227. #Region " Public Methods "
  228.  
  229.        ''' ----------------------------------------------------------------------------------------------------
  230.        ''' <summary>
  231.        ''' Starts monitoring.
  232.        ''' </summary>
  233.        ''' ----------------------------------------------------------------------------------------------------
  234.        ''' <exception cref="Exception">
  235.        ''' Monitor is already running.
  236.        ''' </exception>
  237.        ''' ----------------------------------------------------------------------------------------------------
  238.        <DebuggerStepThrough>
  239.        Public Overridable Sub Start()
  240.  
  241.            If (Me.Handle = IntPtr.Zero) Then
  242.                MyBase.CreateHandle(New CreateParams())
  243.                Me.isRunningB = True
  244.  
  245.            Else
  246.                Throw New Exception(message:="Monitor is already running.")
  247.  
  248.            End If
  249.  
  250.        End Sub
  251.  
  252.        ''' ----------------------------------------------------------------------------------------------------
  253.        ''' <summary>
  254.        ''' Stops monitoring.
  255.        ''' </summary>
  256.        ''' ----------------------------------------------------------------------------------------------------
  257.        ''' <exception cref="Exception">
  258.        ''' Monitor is already stopped.
  259.        ''' </exception>
  260.        ''' ----------------------------------------------------------------------------------------------------
  261.        <DebuggerStepThrough>
  262.        Public Overridable Sub [Stop]()
  263.  
  264.            If (Me.Handle <> IntPtr.Zero) Then
  265.                Me.isRunningB = False
  266.                MyBase.DestroyHandle()
  267.  
  268.            Else
  269.                Throw New Exception(message:="Monitor is already stopped.")
  270.  
  271.            End If
  272.  
  273.        End Sub
  274.  
  275. #End Region
  276.  
  277. #Region " Private Methods "
  278.  
  279.        ''' ----------------------------------------------------------------------------------------------------
  280.        ''' <summary>
  281.        ''' Gets the drive letter stored in a <see cref="DevBroadcastVolume"/> structure.
  282.        ''' </summary>
  283.        ''' ----------------------------------------------------------------------------------------------------
  284.        ''' <param name="device">
  285.        ''' The <see cref="DevBroadcastVolume"/> structure containing the device mask.
  286.        ''' </param>
  287.        ''' ----------------------------------------------------------------------------------------------------
  288.        ''' <returns>
  289.        ''' The drive letter.
  290.        ''' </returns>
  291.        ''' ----------------------------------------------------------------------------------------------------
  292.        <DebuggerStepThrough>
  293.        Protected Overridable Function GetDriveLetter(ByVal device As DevBroadcastVolume) As Char
  294.  
  295.            Dim driveLetters As Char() = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray
  296.  
  297.            Dim deviceID As New BitArray(BitConverter.GetBytes(device.Mask))
  298.  
  299.            For i As Integer = 0 To deviceID.Length
  300.  
  301.                If deviceID(i) Then
  302.                    Return driveLetters(i)
  303.                End If
  304.  
  305.            Next i
  306.  
  307.            Return Nothing
  308.  
  309.        End Function
  310.  
  311. #End Region
  312.  
  313. #Region " Window Procedure (WndProc) "
  314.  
  315.        ''' ----------------------------------------------------------------------------------------------------
  316.        ''' <summary>
  317.        ''' Invokes the default window procedure associated with this window to process windows messages.
  318.        ''' </summary>
  319.        ''' ----------------------------------------------------------------------------------------------------
  320.        ''' <param name="m">
  321.        ''' A <see cref="Message"/> that is associated with the current Windows message.
  322.        ''' </param>
  323.        ''' ----------------------------------------------------------------------------------------------------
  324.        <DebuggerStepThrough>
  325.        Protected Overrides Sub WndProc(ByRef m As Message)
  326.  
  327.            Select Case m.Msg
  328.  
  329.                Case DeviceEvents.Change ' The hardware has changed.
  330.  
  331.                    If (m.LParam = IntPtr.Zero) Then
  332.                        Exit Select
  333.                    End If
  334.  
  335.                    ' If it's an storage device then...
  336.                    If Marshal.ReadInt32(m.LParam, 4) = DeviceType.Logical Then
  337.  
  338.                        ' Transform the LParam pointer into the data structure.
  339.                        Dim currentWDrive As DevBroadcastVolume =
  340.                            DirectCast(Marshal.PtrToStructure(m.LParam, GetType(DevBroadcastVolume)), DevBroadcastVolume)
  341.  
  342.                        Dim driveLetter As Char = Me.GetDriveLetter(currentWDrive)
  343.                        Dim deviceEvent As DeviceEvents = DirectCast(m.WParam.ToInt32, DeviceEvents)
  344.                        Dim driveInfo As New DriveInfo(driveLetter)
  345.  
  346.                        Me.OnDriveStatusChanged(New DriveStatusChangedEventArgs(deviceEvent, driveInfo))
  347.  
  348.                    End If
  349.  
  350.            End Select
  351.  
  352.            ' Return Message to base message handler.
  353.            MyBase.WndProc(m)
  354.  
  355.        End Sub
  356.  
  357. #End Region
  358.  
  359. #Region " IDisposable Implementation "
  360.  
  361.        ''' ----------------------------------------------------------------------------------------------------
  362.        ''' <summary>
  363.        ''' Flag to detect redundant calls when disposing.
  364.        ''' </summary>
  365.        ''' ----------------------------------------------------------------------------------------------------
  366.        Private isDisposed As Boolean
  367.  
  368.        ''' ----------------------------------------------------------------------------------------------------
  369.        ''' <summary>
  370.        ''' Releases all the resources used by this instance.
  371.        ''' </summary>
  372.        ''' ----------------------------------------------------------------------------------------------------
  373.        <DebuggerStepThrough>
  374.        Public Sub Dispose() Implements IDisposable.Dispose
  375.  
  376.            Me.Dispose(isDisposing:=True)
  377.            GC.SuppressFinalize(obj:=Me)
  378.  
  379.        End Sub
  380.  
  381.        ''' ----------------------------------------------------------------------------------------------------
  382.        ''' <summary>
  383.        ''' Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  384.        ''' Releases unmanaged and, optionally, managed resources.
  385.        ''' </summary>
  386.        ''' ----------------------------------------------------------------------------------------------------
  387.        ''' <param name="isDisposing">
  388.        ''' <see langword="True"/>  to release both managed and unmanaged resources;
  389.        ''' <see langword="False"/> to release only unmanaged resources.
  390.        ''' </param>
  391.        ''' ----------------------------------------------------------------------------------------------------
  392.        <DebuggerStepThrough>
  393.        Protected Overridable Sub Dispose(ByVal isDisposing As Boolean)
  394.  
  395.            If (Not Me.isDisposed) AndAlso (isDisposing) Then
  396.                Me.events.Dispose()
  397.                If Me.isRunningB Then
  398.                    Me.Stop()
  399.                End If
  400.            End If
  401.  
  402.            Me.isDisposed = True
  403.  
  404.        End Sub
  405.  
  406. #End Region
  407.  
  408.    End Class
  409.  
  410. End Namespace
  411.  
  412. #End Region
  413.  

DriveStatusChangedEventArgs.vb
Código
  1. ' ***********************************************************************
  2. ' Author   : Elektro
  3. ' Modified : 10-November-2015
  4. ' ***********************************************************************
  5.  
  6. #Region " Public Members Summary "
  7.  
  8. #Region " Constructors "
  9.  
  10. ' New(DeviceEvents, DriveInfo)
  11.  
  12. #End Region
  13.  
  14. #Region " Properties "
  15.  
  16. ' DeviceEvent As DriveWatcher.DeviceEvents
  17. ' DriveInfo As DriveInfo
  18.  
  19. #End Region
  20.  
  21. #End Region
  22.  
  23. #Region " Option Statements "
  24.  
  25. Option Strict On
  26. Option Explicit On
  27. Option Infer Off
  28.  
  29. #End Region
  30.  
  31. #Region " Imports "
  32.  
  33. Imports WindowsApplication1.Win32.Enums
  34.  
  35. ' Imports Elektro.Core.Types
  36. ' Imports Elektro.Interop.Win32.Enums
  37.  
  38. #End Region
  39.  
  40. #Region " DriveStatusChanged EventArgs "
  41.  
  42. Namespace IO.Types.EventArgs
  43.  
  44.    ''' ----------------------------------------------------------------------------------------------------
  45.    ''' <summary>
  46.    ''' Contains the event-data of a <see cref="DriveWatcher.DriveStatusChanged"/> event.
  47.    ''' </summary>
  48.    ''' ----------------------------------------------------------------------------------------------------
  49.    Public NotInheritable Class DriveStatusChangedEventArgs : Inherits System.EventArgs ' : Inherits AestheticEventArgs
  50.  
  51. #Region " Properties "
  52.  
  53.        ''' ----------------------------------------------------------------------------------------------------
  54.        ''' <summary>
  55.        ''' Gets the device event that occurred.
  56.        ''' </summary>
  57.        ''' ----------------------------------------------------------------------------------------------------
  58.        ''' <value>
  59.        ''' The drive info.
  60.        ''' </value>
  61.        ''' ----------------------------------------------------------------------------------------------------
  62.        Public ReadOnly Property DeviceEvent As DeviceEvents
  63.            <DebuggerStepThrough>
  64.            Get
  65.                Return Me.deviceEventsB
  66.            End Get
  67.        End Property
  68.        ''' ----------------------------------------------------------------------------------------------------
  69.        ''' <summary>
  70.        ''' ( Backing field )
  71.        ''' The device event that occurred.
  72.        ''' </summary>
  73.        ''' ----------------------------------------------------------------------------------------------------
  74.        Private ReadOnly deviceEventsB As DeviceEvents
  75.  
  76.        ''' ----------------------------------------------------------------------------------------------------
  77.        ''' <summary>
  78.        ''' Gets the drive info.
  79.        ''' </summary>
  80.        ''' ----------------------------------------------------------------------------------------------------
  81.        ''' <value>
  82.        ''' The drive info.
  83.        ''' </value>
  84.        ''' ----------------------------------------------------------------------------------------------------
  85.        Public ReadOnly Property DriveInfo As DriveInfo
  86.            <DebuggerStepThrough>
  87.            Get
  88.                Return Me.driveInfoB
  89.            End Get
  90.        End Property
  91.        ''' ----------------------------------------------------------------------------------------------------
  92.        ''' <summary>
  93.        ''' ( Backing field )
  94.        ''' The drive info.
  95.        ''' </summary>
  96.        ''' ----------------------------------------------------------------------------------------------------
  97.        Private ReadOnly driveInfoB As DriveInfo
  98.  
  99. #End Region
  100.  
  101. #Region " Constructors "
  102.  
  103.        ''' ----------------------------------------------------------------------------------------------------
  104.        ''' <summary>
  105.        ''' Prevents a default instance of the <see cref="DriveStatusChangedEventArgs"/> class from being created.
  106.        ''' </summary>
  107.        ''' ----------------------------------------------------------------------------------------------------
  108.        <DebuggerNonUserCode>
  109.        Private Sub New()
  110.        End Sub
  111.  
  112.        ''' ----------------------------------------------------------------------------------------------------
  113.        ''' <summary>
  114.        ''' Initializes a new instance of the <see cref="DriveStatusChangedEventArgs"/> class.
  115.        ''' </summary>
  116.        ''' ----------------------------------------------------------------------------------------------------
  117.        ''' <param name="driveInfo">
  118.        ''' The drive info.
  119.        ''' </param>
  120.        ''' ----------------------------------------------------------------------------------------------------
  121.        <DebuggerStepThrough>
  122.        Public Sub New(ByVal deviceEvent As DeviceEvents, ByVal driveInfo As DriveInfo)
  123.  
  124.            Me.deviceEventsB = deviceEvent
  125.            Me.driveInfoB = driveInfo
  126.  
  127.        End Sub
  128.  
  129. #End Region
  130.  
  131.    End Class
  132.  
  133. End Namespace
  134.  
  135. #End Region
  136.  

DeviceEvents.vb
Código
  1. ' ***********************************************************************
  2. ' Author   : Elektro
  3. ' Modified : 10-November-2015
  4. ' ***********************************************************************
  5.  
  6. #Region " Option Statements "
  7.  
  8. Option Strict On
  9. Option Explicit On
  10. Option Infer Off
  11.  
  12. #End Region
  13.  
  14. #Region " Device Events "
  15.  
  16. Namespace Win32.Enums
  17.  
  18.    ''' ----------------------------------------------------------------------------------------------------
  19.    ''' <summary>
  20.    ''' Specifies a change to the hardware configuration of a device.
  21.    ''' </summary>
  22.    ''' ----------------------------------------------------------------------------------------------------
  23.    ''' <remarks>
  24.    ''' <see href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363480%28v=vs.85%29.aspx"/>
  25.    ''' <para></para>
  26.    ''' <see href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363232%28v=vs.85%29.aspx"/>
  27.    ''' </remarks>
  28.    ''' ----------------------------------------------------------------------------------------------------
  29.    Public Enum DeviceEvents As Integer
  30.  
  31.        ' *****************************************************************************
  32.        '                            WARNING!, NEED TO KNOW...
  33.        '
  34.        '  THIS ENUMERATION IS PARTIALLY DEFINED TO MEET THE PURPOSES OF THIS API
  35.        ' *****************************************************************************
  36.  
  37.        ''' <summary>
  38.        ''' The current configuration has changed, due to a dock or undock.
  39.        ''' </summary>
  40.        Change = &H219
  41.  
  42.        ''' <summary>
  43.        ''' A device or piece of media has been inserted and becomes available.
  44.        ''' </summary>
  45.        Arrival = &H8000
  46.  
  47.        ''' <summary>
  48.        ''' Request permission to remove a device or piece of media.
  49.        ''' <para></para>
  50.        ''' This message is the last chance for applications and drivers to prepare for this removal.
  51.        ''' However, any application can deny this request and cancel the operation.
  52.        ''' </summary>
  53.        QueryRemove = &H8001
  54.  
  55.        ''' <summary>
  56.        ''' A request to remove a device or piece of media has been canceled.
  57.        ''' </summary>
  58.        QueryRemoveFailed = &H8002
  59.  
  60.        ''' <summary>
  61.        ''' A device or piece of media is being removed and is no longer available for use.
  62.        ''' </summary>
  63.        RemovePending = &H8003
  64.  
  65.        ''' <summary>
  66.        ''' A device or piece of media has been removed.
  67.        ''' </summary>
  68.        RemoveComplete = &H8004
  69.  
  70.    End Enum
  71.  
  72. End Namespace
  73.  
  74. #End Region
  75.  

DevBroadcastVolume.vb
Código
  1. ' ***********************************************************************
  2. ' Author   : Elektro
  3. ' Modified : 10-November-2015
  4. ' ***********************************************************************
  5.  
  6. #Region " Option Statements "
  7.  
  8. Option Strict On
  9. Option Explicit On
  10. Option Infer Off
  11.  
  12. #End Region
  13.  
  14. #Region " Imports "
  15.  
  16. Imports System.Runtime.InteropServices
  17.  
  18. #End Region
  19.  
  20. #Region " DevBroadcast Volume "
  21.  
  22. Namespace Win32.Types
  23.  
  24.    ''' ----------------------------------------------------------------------------------------------------
  25.    ''' <summary>
  26.    ''' Contains information about a logical volume.
  27.    ''' </summary>
  28.    ''' ----------------------------------------------------------------------------------------------------
  29.    ''' <remarks>
  30.    ''' <see href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363249%28v=vs.85%29.aspx"/>
  31.    ''' </remarks>
  32.    ''' ----------------------------------------------------------------------------------------------------
  33.    <DebuggerStepThrough>
  34.    <StructLayout(LayoutKind.Sequential)>
  35.    Public Structure DevBroadcastVolume
  36.  
  37.        ''' ----------------------------------------------------------------------------------------------------
  38.        ''' <summary>
  39.        ''' The size of this structure, in bytes.
  40.        ''' </summary>
  41.        ''' ----------------------------------------------------------------------------------------------------
  42.        Public Size As UInteger
  43.  
  44.        ''' ----------------------------------------------------------------------------------------------------
  45.        ''' <summary>
  46.        ''' Set to DBT_DEVTYP_VOLUME (2).
  47.        ''' </summary>
  48.        ''' ----------------------------------------------------------------------------------------------------
  49.        Public Type As UInteger
  50.  
  51.        ''' ----------------------------------------------------------------------------------------------------
  52.        ''' <summary>
  53.        ''' Reserved parameter; do not use this.
  54.        ''' </summary>
  55.        ''' ----------------------------------------------------------------------------------------------------
  56.        Public Reserved As UInteger
  57.  
  58.        ''' ----------------------------------------------------------------------------------------------------
  59.        ''' <summary>
  60.        ''' The logical unit mask identifying one or more logical units.
  61.        ''' Each bit in the mask corresponds to one logical drive.
  62.        ''' Bit 0 represents drive A, bit 1 represents drive B, and so on.
  63.        ''' </summary>
  64.        ''' ----------------------------------------------------------------------------------------------------
  65.        Public Mask As UInteger
  66.  
  67.        ''' ----------------------------------------------------------------------------------------------------
  68.        ''' <summary>
  69.        ''' This parameter can be one of the following values:
  70.        ''' '0x0001': Change affects media in drive. If not set, change affects physical device or drive.
  71.        ''' '0x0002': Indicated logical volume is a network volume.
  72.        ''' </summary>
  73.        ''' ----------------------------------------------------------------------------------------------------
  74.        Public Flags As UShort
  75.  
  76.    End Structure
  77.  
  78. End Namespace
  79.  
  80. #End Region
  81.  



Por último, esto de aquí abajo seria uno de los posibles algoritmos que se podría elaborar para el copiado de archivos. Para llevarlo a cabo simplemente he reciclado y adaptado el código que ya te enseñé en este otro post:
...por eso lo he dejado tan "en bruto" y con lineas comentadas, para denotar las diferencias entre uno y otro código.

Código
  1. Imports System
  2. Imports WindowsApplication1.IO.Types
  3. Imports WindowsApplication1.IO.Types.EventArgs
  4.  
  5. Public NotInheritable Class Form1 : Inherits Form
  6.  
  7.    Friend WithEvents DriveMon As New DriveWatcher()
  8.    Private ReadOnly outDir As String = "C:\Monitor\"
  9.  
  10.    ''' ----------------------------------------------------------------------------------------------------
  11.    ''' <summary>
  12.    ''' Handles the <see cref="DriveWatcher.DriveStatusChanged"/> event of the <see cref="DriveMon"/> instance.
  13.    ''' </summary>
  14.    ''' ----------------------------------------------------------------------------------------------------
  15.    ''' <param name="sender">
  16.    ''' The source of the event.
  17.    ''' </param>
  18.    '''
  19.    ''' <param name="e">
  20.    ''' The <see cref="DriveStatusChangedEventArgs"/> instance containing the event data.
  21.    ''' </param>
  22.    ''' ----------------------------------------------------------------------------------------------------
  23.    Private Sub DriveMon_DriveStatusChanged(ByVal sender As Object, ByVal e As DriveStatusChangedEventArgs) Handles DriveMon.DriveStatusChanged
  24.  
  25.        Select Case e.DeviceEvent
  26.  
  27.            Case Win32.Enums.DeviceEvents.Arrival
  28.                Dim sb As New StringBuilder
  29.                With sb
  30.                    .AppendLine("New drive connected...'")
  31.                    .AppendLine(String.Format("Name: {0}", e.DriveInfo.Name))
  32.                    .AppendLine(String.Format("Root.: {0}", e.DriveInfo.RootDirectory))
  33.                    .AppendLine(String.Format("Label: {0}", e.DriveInfo.VolumeLabel))
  34.                    .AppendLine(String.Format("Size.: {0} GB", (e.DriveInfo.TotalSize / (1024 ^ 3)).ToString("n1")))
  35.                End With
  36.                Console.WriteLine(sb.ToString())
  37.                Console.WriteLine("Initializing copy...")
  38.  
  39.                Dim copyTask As Task(Of Integer) = Me.CopyFiles(e.DriveInfo.VolumeLabel, e.DriveInfo.RootDirectory.FullName, outDir)
  40.                ' Await Task.WhenAll(copyTask)
  41.  
  42.            Case Win32.Enums.DeviceEvents.RemoveComplete
  43.                Dim sb As New StringBuilder
  44.                With sb
  45.                    .AppendLine("Drive disconnected...'")
  46.                    .AppendLine(String.Format("Name: {0}", e.DriveInfo.Name))
  47.                    sb.AppendLine(String.Format("Root: {0}", e.DriveInfo.RootDirectory))
  48.                End With
  49.                Console.WriteLine(sb.ToString())
  50.  
  51.        End Select
  52.  
  53.    End Sub
  54.  
  55.    Private Sub StartMon_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button_StartMon.Click
  56.        Me.DriveMon.Start()
  57.    End Sub
  58.  
  59.    Private Sub StopMon_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button_StopMon.Click
  60.        Me.DriveMon.Stop()
  61.    End Sub
  62.  
  63.    Public Async Function CopyFiles(ByVal labelName As String, ByVal srcDirPath As String, ByVal dstDirPath As String) As Task(Of Integer)
  64.  
  65.        Dim filesDict As New Dictionary(Of FileInfo, FileInfo) ' {[Key: Source File], [Value: Destination File]}
  66.  
  67.        For Each file As FileInfo In New DirectoryInfo(srcDirPath).EnumerateFiles("*", SearchOption.AllDirectories)
  68.            Dim srcRoot As String = file.Directory.Root.FullName
  69.            Dim dstFilepath As String = file.FullName.Replace(srcRoot, Path.Combine(Me.outDir, labelName) & "\")
  70.            filesDict.Add(file, New FileInfo(dstFilepath))
  71.        Next file
  72.  
  73.        ' Dim maxFileCount As Integer = filesDict.Count()
  74.        ' Dim curFileCount As Integer
  75.  
  76.        ' Dim updateLabelCallback As New SendOrPostCallback(
  77.        '     Sub(ByVal state As Object)
  78.        '         progressCtrl.Text = String.Format("{0} of {1} files copied...", CInt(state), maxFileCount)
  79.        '     End Sub)
  80.  
  81.        Dim copySingleFileAction As New Action(Of KeyValuePair(Of FileInfo, FileInfo))(
  82.            Sub(ByVal pair As KeyValuePair(Of FileInfo, FileInfo))
  83.                Try
  84.                    If Not (pair.Value.Directory.Exists) Then
  85.                        pair.Value.Directory.Create()
  86.                    End If
  87.                    pair.Key.CopyTo(pair.Value.FullName, overwrite:=False)
  88.                    ' SynchronizationContext.Current.Post(updateLabelCallback, Interlocked.Increment(curFileCount))
  89.                Catch ex As Exception
  90.                End Try
  91.            End Sub)
  92.  
  93.        Dim copyAllFilesFunc As Func(Of Integer) =
  94.            Function() As Integer
  95.                ' Parallel.ForEach(Of KeyValuePair(Of FileInfo, FileInfo))(filesDict, copySingleFileAction)
  96.                ' -- Sin paralelismo en este caso es más eficiente.
  97.                For Each pair As KeyValuePair(Of FileInfo, FileInfo) In filesDict
  98.                    copySingleFileAction(pair)
  99.                Next
  100.                ' Return curFileCount ' Return the amount of files that were copied.
  101.            End Function
  102.  
  103.        If Not New DirectoryInfo(dstDirPath).Exists Then
  104.            Directory.CreateDirectory(dstDirPath, Nothing)
  105.        End If
  106.  
  107.        Dim t As New Task(Of Integer)(copyAllFilesFunc, TaskCreationOptions.LongRunning)
  108.        t.Start()
  109.        Await t
  110.  
  111.        Return t.Result
  112.    End Function
  113.  
  114. End Class

De esa manera, se ejecutará de forma automática y asíncrona una tarea que iniciará el copiado de archivos por cada dispositivo extraible de almacenamiento que insertes en el PC en cuestión. Los archivos se copiarán del USB a la carpeta destino especificada, conservando la estructura de directorios de la ruta del archivo de origen a copiar. Si extraes un USB durante una operación de copiado, simplemente se disparará una excepción controlada que ignorará el copiado, y podrás reinsertar el mismo USB para seguir la copia, o insertar un nuevo USB. Puedes ocupar varias ranuras de USB de forma simultanea para copair varios dispositivos al mismo tiempo. Y creo que no me dejo nada destacable por mencionar sobre la funcionalidad del código.

Cabe mencionar que el código no está optimizado, tan solo es un ejemplo básico pero funcional para lograr lo que quieres, pues no voy a ponerme a hacerte yo todo el trabajo y escribir aquí la de Dios. Te recomiendo añadir controles de errores al menos para evaluar los permisos de usuario de la carpeta destino, además también podrías habilitar la capacidad de poder cancelar al instante una operación de copiado que esté en curso al momento de extraer un dispositivo USB, esto lo harias mediante el la creación y el uso de un token de cancelación el cual lo pasarías como argumento a una de las sobrecargas del método Task.Start(), y evaluarias una petición de cancelación en el bloque del método CopyFiles del código que te mostré. Otra cosa que se puede mejorar es el orden de iteración/copiado de archivos, podrías ordenar la colección para que se procesen los archivos de menor tamaño a mayor, dependiendo de tus necesidades.
En fin, puedes improvisar ese código de ejemplo de mil maneras distintas para perfeccionarlo.

¡Saludos!
« Última modificación: 27 Febrero 2017, 16:21 por Eleкtro » En línea


NEBIRE

Desconectado Desconectado

Mensajes: 285


Ver Perfil
Re: Ayuda con Copiador de USB
« Respuesta #4 en: 20 Abril 2017, 01:55 »

Curiosamente encontré que el VBTeam (el equipo de visual Basic), en su página han hablado de esto (hace apenas una semana), parece como si nos hubieran leído...

Aportan algunas soluciones más, que aunque óptimas, creo que son más complicadas para usuarios noveles. Vale la pena hecharles un vistazo:
https://blogs.msdn.microsoft.com/vbteam/2017/04/10/easy-async-and-await-for-vbs-part-1-or/

...es la parte 1, o sea que posiblemente vuelvan en otro momento a retomar el tema...
En línea

Maurice_Lupin

Desconectado Desconectado

Mensajes: 298


GPS


Ver Perfil WWW
Re: Ayuda con Copiador de USB
« Respuesta #5 en: 22 Abril 2017, 20:07 »

Buenos codigos, voy a experimentar con ellos para hacer bromas a mis amigos, sólo que en lugar de copiar será cortar :xD

Saludos.
En línea

Un error se comete al equivocarse.
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
copiador de websites
Hacking Básico
h4z3 9 3,501 Último mensaje 19 Abril 2004, 17:09
por el-brujo
USB copiador o algo así (ayuda) « 1 2 3 »
Hacking Básico
estudcom 26 13,906 Último mensaje 20 Noviembre 2008, 03:31
por monorott
[Aporte] Copiador de bytes en un mismo medio
Java
Debci 2 1,349 Último mensaje 29 Noviembre 2009, 20:44
por Debci
USB (Copiador de Datos de la Pc) « 1 2 »
Hacking Básico
WiseHidden 19 6,992 Último mensaje 2 Octubre 2012, 18:40
por ESCORPION92_92
Copiador bat
Scripting
tomasscfgcu 3 635 Último mensaje 28 Mayo 2015, 17:02
por Eleкtro
Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines