[VB.NET]Copier le dernier item listbox sur son disque dur

Résolu
Utilisateur anonyme - 6 mars 2013 à 15:41
 Utilisateur anonyme - 31 mars 2013 à 21:19
Bonjour,
je suis en train de développer une application qui liste certains types de fichiers et qui donne la possibilité de les sauvegarder dans le répertoire de l'application.
Je vous explique comment se présente l'application :
• Il y a une partie graphique où tous les fichiers trouvés sont listés dans une listbox à l'aide de thread. Une fois le listage fini, si l'on appuie sur le bouton copier, tous les fichiers se copient à l'aide de ce code :
 Try
            Dim file As FileInfo
            For Each fileitem In ListboxFichiersTrouvés.Items
                file = New FileInfo(fileitem)
                Dim FileSize As Long = file.Length
                Dim Taille As Long = TextBoxTailleMinimumCopieFichier.Text * 1024
                If TextBoxTailleMinimumCopieFichier.Text = "Taille du fichier minimum pour copier ( KO )" Then
                    Taille = "0"
                End If
                If file.Length > Taille Then
                    file.CopyTo(Path.Combine(Application.StartupPath, file.Name), True)
                End If
            Next
        Catch
            Call CopyDesFichiers()
        End Try


Le code marche très bien car le listage est fini, cependant j'aimerais pouvoir copier à chaque fois qu'un nouvel item apparait.
J'ai donc inséré un thread qui appel ma fonction copie lorsqu'un item est ajouté :
    Private Sub RemplirListe(ByVal Fichier As IO.FileInfo)
        ListboxFichiersTrouvés.Items.Add(Fichier.FullName)
        ListboxFichiersTrouvés.SelectedIndex = ListboxFichiersTrouvés.Items.Count - 1
 Dim p As New Threading.Thread(AddressOf CopieDesFichiers)
                    p.Start
        ListboxFichiersTrouvés.Refresh()
    End Sub


Cependant, l'application n'est pas fluide car je suppose que le listage se fait plus vite que le copiage.

Je ne trouve donc pas de moyen pour contourner le problème, ou alors ce que je pourrais faire c'est dans ma fonction CopieDesFichiers lui indiquer à la place de
For Each fileitem In ListboxFichiersTrouvés.Items juste le dernier item par exemple avec ce bout de code mais il représente une valeur booléenne donc ça ne fonctionne pas :'(
ListboxFichiersTrouvés.SelectedIndex = ListboxFichiersTrouvés.Items.Count - 1

19 réponses

Utilisateur anonyme
31 mars 2013 à 21:19
Voilà avec banana on a réussi suite à de nombreux tests à trouver la bonne solution :)

Sub RemplirListe(ByVal Fichier As IO.FileInfo)
        If Not My.Computer.FileSystem.FileExists(IO.Path.Combine(Application.StartupPath, Fichier.Name)) Then
            ListboxFichiersTrouvés.Items.Add(Fichier.FullName)
            ListboxFichiersTrouvés.SelectedIndex = ListboxFichiersTrouvés.Items.Count - 1
            Try
                If Not My.Computer.FileSystem.FileExists(IO.Path.Combine(Application.StartupPath, Fichier.Name)) Then
                    If Application.StartupPath <> Fichier.FullName Then
                        Fichier.CopyTo(IO.Path.Combine(Application.StartupPath, Fichier.Name), True)
                    End If
                End If
            Catch ex As Exception
            End Try
            ListboxFichiersTrouvés.Refresh()
            col.Enqueue(Fichier)
            LabelNombreFichiersTrouves.Text = ListboxFichiersTrouvés.Items.Count
        Else
        End If
3
ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 211
6 mars 2013 à 16:44
Bonjour,
m'a pas l'air d'être du :
Forum > Visual Basic 6

ce bout de code !


________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviendrai que si nécessité de la compléter.
0
Utilisateur anonyme
6 mars 2013 à 16:49
Ah oui je voulais poster en VB.NET, désolé je me suis trompé si vous voulez bien déplacer le sujet ;)
0
Utilisateur anonyme
6 mars 2013 à 19:56
Bonjour,

Le code marche très bien
En activant Option Strict, non ton code ne marche pas désolé...

C'est une très mauvaise idée que de se baser sur un contrôle (donc ton listbox) pour y récupérer des informations et effectuer des opérations. Ton contrôle ne devrait se contenter que d'un affichage. Je te conseille d'utiliser une collection premier entré, premier sorti du style Queue. (voir Collections.Queue)

Dim col As New Collections.Queue
Dim monfichier As ???
'...
'ajouter
col.Enqueue(monfichier)
'...
'récupérer en consommant
Dim monfichier As ??? = CType(col.Dequeue, ???)

'tester sans consommer
Dim monfichier As ??? = CType(col.Peek, ???) 


Ton listbox se contentera d'afficher le contenu de ta collection.

A préciser qu'un simple label suffirait à afficher le fichier en cours de déplacement. L'utilisateur lambda se fout complètement de savoir ce que fait une application du moment qu'elle fait le job voulu.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Utilisateur anonyme
8 mars 2013 à 09:15
Salut banana32
J'ai cherché la collection queue sur le MSDN http://msdn.microsoft.com/fr-fr/library/system.collections.queue.aspx et la méthode CopyTo me semble appropriée à mon problème seulement, je ne sais pas du tout comment l'utiliser. Pourrais-tu me donner des explications sur comment l'utiliser car en plus la description est : "Copie les éléments Queue dans un Array unidimensionnel existant, en commençant au niveau de l'index de tableau spécifié." et donc ça collerait avec ma ListBox que je veux garder non ?
Merci de ton aide !
0
ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 211
8 mars 2013 à 09:30
J'ai cherché la [quote]collection queue
sur le MSDN

/quote
MSDN n'est pas (encore ?) un site porno !
________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviendrai que si nécessité de la compléter.
0
Utilisateur anonyme
8 mars 2013 à 19:23
C'est pas moi qui ai inventé le nom de la classe ...
0
Utilisateur anonyme
8 mars 2013 à 19:57
Une collection premier entré premier sorti, c'est comme un tapis roulant dans un supermarché. La caissière ajoute les articles sur son tapis et toi tu les prends de l'autre côté pour les ranger (donc le premier qu'elle à posé est le premier sorti). Si tu traines trop, les articles seront de plus en plus nombreux sur le tapis.
Enqueue c'est la caissière.
Dequeue c'est toi.
Peek c'est le vigile du magasin qui veut s'assurer du prix de l'article que tu veux prendre et qui le repose à sa place sur le tapis.

Ce que doit afficher ta liste, c'est ce qu'il y a sur le tapis. Donc ni ceux que tu as déjà rangé, ni ceux que la caissière n'a pas encore mis sur le tapis.

L'avantage, c'est que peu importe la rapidité de la caissière ou ta lenteur à toi, tu auras toujours à disposition l'article que tu dois ranger.
0
Utilisateur anonyme
9 mars 2013 à 00:04
Merci j'ai maintenant parfaitement compris le principe de cette classe, mais ce que je ne comprends pas c'est comment je dois l'intégrer à mon application, c'est à dire est-ce que je dois garder ma listbox et transférer les items dans la collection ? Ou supprimer ma listbox et lister directement dans la collection ...
Si tu veux les codes de l'application banana ils sont là :
http://www.vbfrance.com/forum/sujet-RECUPERER-TOUS-JPG-PC_1606962.aspx?p=3
http://www.vbfrance.com/forum/sujet-APPELER-FONCTION-AVEC-PARAMETRES-DANS-BACKGROUNDWORKER_1616364.aspx

Merci encore :)
0
Utilisateur anonyme
9 mars 2013 à 00:55
Ce que je veux te faire comprendre, c'est que tu dois travailler sur la Queue plutôt que sur le listbox. Surtout si tu mets en oeuvre plusieurs threads. Il peut se rajouter plusieurs items à celle-ci pendant que tu traites encore un item précédent. Tu ne peux donc pas prendre le dernier item à un instant t car il va t'en manquer. Et le (ou les) threads de traitement risquent de prendre le même fichier (si le listage prends du temps) pour le déplacer.

Je sais c'est pas très français tout ça. Il faut que je prenne des cours.

Donc d'après ton code, pour ajouter :
col.Enqueue(file)


Et dans un (ou plusieurs) thread par exemple qui sera démarré à moment donné (a toi de fixer les conditions) :
sub job
   'boucle qui devra se terminer lorsque la variable 'finliste' sera
   'mise à true en fin de listage de tes fichiers (voir ta fonction)
   do 
       if col.count > 0 then
          'récupération du fichier premier entré
          dim monfichier as io.fileinfo = ctype(col.dequeue,io.fileinfo)
          'déplacement du fichier
          my.computer.filesystem.movefile(monfichier.fullpath...
       end if
   loop while not finliste
end sub
0
Utilisateur anonyme
11 mars 2013 à 21:51
Salut,
je galère vraiment avec cette classe malgré vos explications. J'ai fait ce petit bout de code mais je ne sais même pas si il est bon ...
fin est une variable booléenne.
    Sub job()
        Dim col As New Collections.Queue
        Dim File As FileInfo
        col.Enqueue(File)
        'boucle qui devra se terminer lorsque la variable 'finliste' sera
        'mise à true en fin de listage de tes fichiers (voir ta fonction)
        Do
            If col.count > 0 Then
                'récupération du fichier premier entré
                Dim monfichier As IO.FileInfo = CType(col.dequeue, IO.FileInfo)
                'déplacement du fichie

                File.CopyTo(Path.Combine(Application.StartupPath, File.Name), True)
            End If
        Loop While fin = False
    End Sub


Je pense donc malheureusement abandonner cette classe parce que j'ai peut être trouvé une alternative.
En effet, mon logiciel cherche tous les fichiers et une fois qu'il à fini son analyse, il entre dans :
( Cependant c'est ce que je vois dans le pas à pas, après peut être que le logiciel fait le thread et que je ne le vois pas dans le pas à pas et qu'en même temps il liste ? )
Private Sub RemplirListe(ByVal Fichier As IO.FileInfo)
        ListboxFichiersTrouvés.Items.Add(Fichier.FullName)
        ListboxFichiersTrouvés.SelectedIndex = ListboxFichiersTrouvés.Items.Count - 1
        ListboxFichiersTrouvés.Refresh()

    End Sub


Il faudrait en fait que je puisse détecter lorsque le logiciel à fini de lister en boucle, je pensais à un truc du genre si le il ne change pas de ligne ( qu'il n’exécute plus d'actions au bout de X secondes), copier la listbox.
Vous pensez que c'est bon ? Et est-ce que vous avez une idée de comment faire ?
Merci !
0
Utilisateur anonyme
11 mars 2013 à 22:19
Il y a erreur, c'est plutôt :
Dim monfichier As IO.FileInfo = CType(col.dequeue, IO.FileInfo)
                'déplacement du fichie

                monfichier.CopyTo(Path.Combine(Application.StartupPath, monfichier.Name), True)
0
Utilisateur anonyme
11 mars 2013 à 22:24
Et ce n'est pas ici que l'on ajoute les fichiers à la collection...
Dim File As FileInfo
col.Enqueue(File)

...Mais pendant ta fonction de listage.
0
Utilisateur anonyme
12 mars 2013 à 21:45
Salut banana32,
j'ai placé le code comme je pense qu'il doit l'être, alors j'ai mis dans mon sub remplirliste :
 Sub RemplirListe(ByVal Fichier As IO.FileInfo)
        ListboxFichiersTrouvés.Items.Add(Fichier.FullName)
        ListboxFichiersTrouvés.SelectedIndex = ListboxFichiersTrouvés.Items.Count - 1
        ListboxFichiersTrouvés.Refresh()
        Dim col As New Collections.Queue
        Dim File As FileInfo
        col.Enqueue(File)
        Dim threadcopy As New Threading.Thread(AddressOf job)
        threadcopy.Start()
    End Sub


Et dans le sub job :

    Sub job()
        Dim col As New Collections.Queue
        'boucle qui devra se terminer lorsque la variable 'finliste' sera
        'mise à true en fin de listage de tes fichiers (voir ta fonction)
        Do
            If col.count > 0 Then
                'récupération du fichier premier entré
                Dim monfichier As IO.FileInfo = CType(col.Dequeue, IO.FileInfo)
                'déplacement du fichie

                monfichier.CopyTo(Path.Combine(Application.StartupPath, monfichier.Name), True)
            End If
        Loop While fin = False
    End Sub


Mais le listage se fait très lentement, énormément de fichiers ne sont pas listés, l'application plante et le peu de fichiers trouvés ne sont pas copiés, je me suis dit que c'était à cause du
Dim col As New Collections.Queue[code=vb] je l'ai donc placé tout en haut pour en faire une variable "publique" mais là, l'application plante carrément et une erreur "La référence d'objet n'est pas définie à une instance d'un objet." se produit sur la ligne [code=vb]monfichier.CopyTo(Path.Combine(Application.StartupPath, monfichier.Name), True)


Peut être ai-je fais une erreur dans le code ? Merci encore pour ton aide ^^
0
Utilisateur anonyme
12 mars 2013 à 22:38
1/ L'instance de ta Queue doit se faire avant le listage. Tu peux la déclarer comme ceci dans l'entête de ta classe :
Dim col as Queue

Puis l'instancier juste avant le listage de tes fichiers :
col = new Queue

Supprimer également cette instanciation dans la sub (job) qu'exécute ton thread.

2/ Que vient faire ceci dans ton code ?
Dim File As FileInfo
col.Enqueue(File)

Tu dois simplement fournir à ta collection ta variable 'Fichier' qu'on trouve en paramètre de ta sub :
col.Enqueue(Fichier)


3/ En fin de listage (récursivité terminée) et lorsque tu es sûr que tous les fichiers ont été traités (col.count = 0), ta variable 'fin' devra être mise à true pour stopper le thread. Je me demande même si cette variable est utile finalement. Un simple test des deux conditions (avec And) devrait suffire.
0
Utilisateur anonyme
13 mars 2013 à 20:52
Salut,
j'ai effectué les modifications que tu m'a dit :

Dim col As Queue
en entête.

démarrage du thread ( avec le col = New Queue ):

col = New Queue
            Dim p As New Threading.Thread(AddressOf ChercherFichiers)
            p.Start(New clsObjet(New IO.DirectoryInfo("C:\Users"), New String() {"JPG", "GIF", "BMP", "DXF", "EPS", "PCX", "PICT", "PS", "TIFF", "WPG", "PNG", "MNG"}))


Sub RemplirListe(ByVal Fichier As IO.FileInfo)

        ListboxFichiersTrouvés.Items.Add(Fichier.FullName)
        ListboxFichiersTrouvés.SelectedIndex = ListboxFichiersTrouvés.Items.Count - 1
        ListboxFichiersTrouvés.Refresh()
        col.Enqueue(Fichier)
        If col.Count > 0 Then 'Si je met = 0 la copie des fichiers ne se lance pas ce qui est normal.
            Dim threadcopy As New Threading.Thread(AddressOf job)
            threadcopy.Start()
        End If
   
    End Sub


Le problème est toujours le même, l'application plante, mais au début elle marche bien ( deux fichiers listés et 4 fichiers copiés )
Il faut en fait que je trouve un moyen de avoir quand la sub RemplirListe arrête de s'exécuter, comme ça dès que je sais qu'elle est arrêtée, je lance le thread et la à mon avis ça marchera.
 Sub job()
        'boucle qui devra se terminer lorsque la variable 'finliste' sera
        'mise à true en fin de listage de tes fichiers (voir ta fonction)
        Do
            If col.Count > 0 Then
                'récupération du fichier premier entré
                Dim monfichier As IO.FileInfo = CType(col.Dequeue, IO.FileInfo)
                'déplacement du fichie

                monfichier.CopyTo(Path.Combine(Application.StartupPath, monfichier.Name), True)
            End If
        Loop While fin = False

    End Sub
0
Utilisateur anonyme
13 mars 2013 à 21:34
Ce n'est pas ici que tu dois lancer ton thread, réfléchis un peu.
Dans ce cas un thread sera lancé à chaque nouveau fichier listé.
Ton thread 'threadcopy' doit être lancé au moment ou tu lance le thread de listage.
0
Utilisateur anonyme
14 mars 2013 à 21:52
Oui effectivement ça marche mieux mais pas tout à fait ! ^^ En fait l'application liste et copie en même temps un très grand nombre de fichiers, mais au bout d'un moment ça plante car "ce fichier est déjà utilisé par un autre processus" ( le plantage se fait toujours au même fichier je pense donc qu'il faut attendre le listage des fichiers pour commencer la copie des fichiers.
J'ai donc essayé les codes suivants :
            col = New Queue
            Dim p As New Threading.Thread(AddressOf ChercherFichiers)
            p.Start(New clsObjet(New IO.DirectoryInfo("C:\Users"), New String() {"JPG", "GIF", "BMP", "DXF", "EPS", "PCX", "PICT", "PS", "TIFF", "WPG", "PNG", "MNG"}))
            While p.IsAlive = True
                fin = False
            End While
            fin = True
                Dim threadcopy As New Threading.Thread(AddressOf job)
                threadcopy.Start()


            col = New Queue
            Dim p As New Threading.Thread(AddressOf ChercherFichiers)
            p.Start(New clsObjet(New IO.DirectoryInfo("C:\Users"), New String() {"JPG", "GIF", "BMP", "DXF", "EPS", "PCX", "PICT", "PS", "TIFF", "WPG", "PNG", "MNG"}))
            While p.IsBackground = True
                fin = False
            End While
            fin = True
                Dim threadcopy As New Threading.Thread(AddressOf job)
                threadcopy.Start()


Avec le premier, les fichiers ne se copient pas, avec le second, l'application reste en arrière plan et on ne peut la voire, je verrai demain si je trouve une meilleure solution. En attendant je pense que nous sommes sur la bonne voie !
0
Utilisateur anonyme
15 mars 2013 à 19:26
Salut,
j'ai cherché comment attendre la fin d'un thread et j'ai trouvé la methode join qui me semble la mieux adaptée, seulement il y a quelque chose que je n'arrive pas à comprendre, je ne pense pas pourtant m'être trompé dans l'utilisation de la methode. Lorsque je lance le programme, il n'est pas visible et je ne peux pas le voir, les fichiers ne se copient même pas. Voici ce que j'ai mis :

            col = New Queue
            Dim p As New Threading.Thread(AddressOf ChercherFichiers)
            p.Start(New clsObjet(New IO.DirectoryInfo("C:\Users"), New String() {"JPG", "GIF", "BMP", "DXF", "EPS", "PCX", "PICT", "PS", "TIFF", "WPG", "PNG", "MNG"}))
            p.Join()
            Dim threadcopy As New Threading.Thread(AddressOf job)
            threadcopy.Start()


Je sais que l'on peut utiliser un délai en millisecondes mais je ne trouve pas ça propre si l'utilisateur à un petit disque dur, ou au contraire un grand ...
0
Rejoignez-nous