Rapakooti
Messages postés90Date d'inscriptionmercredi 4 décembre 2002StatutMembreDernière intervention18 mai 2018
-
9 nov. 2012 à 13:42
Rapakooti
Messages postés90Date d'inscriptionmercredi 4 décembre 2002StatutMembreDernière intervention18 mai 2018
-
8 déc. 2012 à 18:22
Bonjour,
je me tourne de nouveau vous, car je rencontre une difficulté.
Je suis en train de developpé un programme qui dans ces fonctions scanné un repertoire que je lui indique pour voir si il y a des fichiers AVI ou MKV, (je vous cache pas que c'est pour gerer mes films de vacances...)
Avant j'indiquais un programme un repertoire, via un bouton ou autre, et cela lancais une procedure, maitenant je veux stocker plusieurs repertoire, des les scanner si besoins ( pour verifier si par exemple de nouveau films sont présent)
VOila mon probleme; j'ai essayé d'intégré cette fonction dans une boucle , mais cela ne fonctionne pas car la procedure peut etre longue car repertoire consequent.
J'ai deja essaye de mettre cette procedure dans des thread, mais cela me provoque une grosse erreur car dans cette procdure il y a creation de thread pour evité que ca fasse figer le programme.... merci d'avoir tenu jusque la lol
Je vois par comment faire a par a la limite via backgrounder mais je n'arrive pas a les utilisé, et je galere avec
Avez vous une idée, ou une ame charitable est elle prete a m'aider.
Voici la procedure en question je l'appel quand j'ai besoin
#region function ajout repertoire
//Procedure d'ajout de film via une recherche recursive
private void Ajoutrep(bool ajout)
{
if (ajout == true)
{
//Creation folderbrowser
FolderBrowserDialog folderDlg = new FolderBrowserDialog();
folderDlg.ShowNewFolderButton = true;
// Montre le FolderBrowserDialog.
DialogResult result = folderDlg.ShowDialog();
// Si le bouton selectionnez est ok >
if (result == DialogResult.OK)
{
if (folderDlg.SelectedPath != "")
{
Trepertoire.Text = folderDlg.SelectedPath;
progressBar1.Visible = true;
progressBar1.Style = ProgressBarStyle.Marquee;
Environment.SpecialFolder root = folderDlg.RootFolder;
// MessageBox.Show("Attention pendant la recherche la fenetre active du programme peut figer", "Attention", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
//lance la recherche recursive
// BPH : vaut-il mieux parcourir l'ensemble des fichiers une fois et tester l'extension
// ou parcourir autant de fois les répertoires que d'extensions a traiter ?
// a determiner par des tests mais je dirais plutot la première option
// (dependante uniquement du nombre de fichiers dans les repertoires qq soit le nb d'extensions a traiter)
// on recupere la liste courante pour ne pas ajouter de doublon
var currentList new HashSet<string>(dataGridView1.Rows.OfType<DataGridViewRow>().Select(r> (string)r.Cells[1].Value));
// on declare ici une tache de fond qui fera le recherche en parallele du "thread UI", evitant ainsi de figer l'interface
// qui peut continuer de recevoir et traiter les evenements de la fenetre.
var task new Task(()>
{
// On utilisera EnumerateFiles qui renvoie les fichiers un a un alors que GetFiles va tous les rechercher d'abord et les renvoyer en une fois dans un tableau
// Avec GetFiles, on ne pourrait pas avoir la liste qui se remplit au fur et a mesure dans la grille
// mathingFiles est ce qu'on appelle une requete Linq, je te laisse decouvrir ca sur le net, cela evite notamment beaucoup de boucles foreach !
// BONUS : j'ai remplacé Directory.EnumerateFiles par une methode perso qui ne plante pas qd elle tombe sur un fichier ou repertoire inaccessible ;-)
var matchingFiles = EnumerateAccessableFiles(Trepertoire.Text, "*", SearchOption.AllDirectories)
.Where(filePath => extensions.Contains(Path.GetExtension(filePath).ToLower())) // ... uniquement les extensions souhaitées
.Where(filePath => excludedKeywords.Any(kw => filePath.Contains(kw)) == false) // ... sans les mots clés exclus
.Where(filePath => currentList.Contains(filePath) == false) // ... et sans doublon
.Select(filePath => new // classes anonyme locale au scope de matchingFiles uniquement
{
HasNFO = File.Exists(Path.GetDirectoryName(filePath) + "/" + Path.GetFileNameWithoutExtension(filePath) + ".nfo"),
FilePath = filePath
});
// le pb avec les controles graphiques est qu'il ne peuvent pas etre modifiés en dehors de leur thread graphique dédié.
// Depuis une tache de fond il faut donc "poster" une fonction qui sera executée dans le contexte du thread UI de la fenetre.
// C'est a cela que serve les methodes BeginInvoke des controles.
// a noter la syntaxe "() =>...", c'est une declaration de methode anonyme en ligne (une lambda)
var count = 0;
foreach (var match in matchingFiles)
{
count++;
dataGridView1.BeginInvoke((Action)(() => dataGridView1.Rows.Add(match.HasNFO, match.FilePath, Path.GetFileName(match.FilePath))));
toolStripStatusLabel1.Text = "Nombres de films : " + dataGridView1.RowCount.ToString();
System.Threading.Thread.Sleep(10);
}
return count;
});
// une continuation permet d'executer du code qd la tache se termine (correctement ou en erreur ou les deux au choix)
task.ContinueWith((t) =>
{
toolStripStatusLabel1.Text = "Nombres de films : " + dataGridView1.RowCount.ToString();
// D'un point de vue ergonomique, il serait preferable de ne pas trier la liste automatiquement a le fin de la recherche
// au risque de perdre la selection et la position courante de l'utilisateur.
// Le mieux serait d'avoir une grille capable de trier les lignes en cliquant sur les entetes de colonnes et de laisser faire l'utilisateur
//dataGridView1.Sort(dataGridView1.Columns[2], ListSortDirection.Ascending);
// attention bug : exception si la liste est vide ;-)
// de plus, cf remarque ci dessus, pour ne pas perdre la selection courante de l'utilisateur
//dataGridView1.CurrentCell = dataGridView1.Rows[0].Cells[2];
// sauvegarde de la liste dans un fichier XML
var actualList dataGridView1.Rows.OfType<DataGridViewRow>().Select(r> new { HasNFO = (bool)r.Cells[0].Value, FilePath = (string)r.Cells[1].Value });
var xDoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
new XElement("VideoList",
actualList.Select(l => new XElement("FilePath", l.FilePath, new XAttribute("HasNFO", l.HasNFO)))));
xDoc.Save(xmlListFilePath);
progressBar1.Visible = false;
progressBar1.Style = ProgressBarStyle.Continuous;
if (t.Result != 0)
{
MessageBox.Show(String.Format("{0} nouveaux fichiers trouvés", t.Result), "Recherche terminée.", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
if (t.Result == 0)
{
MessageBox.Show(String.Format("Pas de nouveau fichier trouvé"), "Recherche terminée.", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
},
TaskScheduler.FromCurrentSynchronizationContext());
// ici on demarre rellement l'exécution de la tache !
task.Start();
}
}
}
}
#endregion
Rapakooti
Messages postés90Date d'inscriptionmercredi 4 décembre 2002StatutMembreDernière intervention18 mai 2018 18 nov. 2012 à 11:26
Oui cela me gêne pas mais j ai déjà tous poste en fait pour l instant j appelle la fonction mit dans mon premier post Ajoutrep(true) avec un empalement dans un textedit. Le passé de paramètre en lui même est pas un souci .
Mais voilà maintenant j ai une listbox avec autant de répertoire que la personne souhaite . Et c est la que le souci commence Ajoutrep ne fonctionne pas dans la boucle foreach de la list car cela lance une nouvelle procédure alors que l ancienne est pas termine .
R A P A K O O T I
Vous n’avez pas trouvé la réponse que vous recherchez ?
Whismeril
Messages postés19025Date d'inscriptionmardi 11 mars 2003StatutContributeurDernière intervention19 avril 2024656 18 nov. 2012 à 11:32
J'ai remanié l'exemple du tuto vite fait, pour trouver 1 word et deux xml rangés dans mon dossier d'exécution, le tout retourné dans une liste de string
string temp = Application.StartupPath;
DirectoryInfo info = new DirectoryInfo(temp);
List<string> query = (from f in info.GetFiles()
where f.Extension ".doc" | f.Extension ".xml"
orderby f.Length descending
select f.Name).ToList<string>() ;
Whismeril
Messages postés19025Date d'inscriptionmardi 11 mars 2003StatutContributeurDernière intervention19 avril 2024656 18 nov. 2012 à 11:40
et voila pour regarder dans 2 répertoires
DirectoryInfo[] infos = new DirectoryInfo[2];
infos[0] = new DirectoryInfo(Application.StartupPath);
infos[1] = new DirectoryInfo(@"c:\temp");
List<string> query = (from info in infos
from f in info.GetFiles()
where f.Extension ".doc" | f.Extension ".xml"
select f.Name).ToList<string>() ;
Whismeril
Messages postés19025Date d'inscriptionmardi 11 mars 2003StatutContributeurDernière intervention19 avril 2024656 18 nov. 2012 à 13:38
Je préfère que la discussion ait lieu ici plutôt qu'en MP.
Evidement que mon code fait moins de choses, je t'ai montré une piste pas ton programme tout refait!
La recherche des doublons c'est assez simple, je vais te faire un exemple et le poster.
Le tri pareil.
L'affichage dans le datagridview, et bien à la fin de la recherche tu affectes la list<string> (ou autre objet) au datasource de la grille ou tu passe par un databindingsource, j'ai posté un tuto là dessus.
La sauvegarde dans un fichier xml, vu que tu as une List<T> tu perds du temps d'exécution à lire le datagridview, sérialize la liste directement. Il y a pleins d'exemple sur le forum, dont des miens.
L'affichage de la progresse bar, bon là avec linq je ne sais pas trop.
Rapakooti
Messages postés90Date d'inscriptionmercredi 4 décembre 2002StatutMembreDernière intervention18 mai 2018 18 nov. 2012 à 13:49
Pour ici lol pas de souci ca reviens au meme pour moi... oui ton compte fait moi de truc mais c est pas le souci je l'ai inteegre au pire apres je peux ajouter des fonctions, le souci c est que comme le code de BarthOlivier il ne s gere pas les lecteurs reseaux... et ca c est un gros souci car tous les repertoire scanne se trouve sur des lecteurs reseau
Whismeril
Messages postés19025Date d'inscriptionmardi 11 mars 2003StatutContributeurDernière intervention19 avril 2024656 18 nov. 2012 à 14:10
Voila un nouvel exemple, j'appelle la fonction LanceDemo (je n'ai pas changé le nom du tuto), qui fait 3 recherches successives avec 4 répertoires, le premier y est toujours et les trois autres font l'objet d'un recherche à chaque fois.
Il y a donc des doublons qui sont traités et un lecteur réseau (enfin presque c'est un réseau virtualbox....).
Et tout ça trié par nom.
public void LanceDemo()
{
DirectoryInfo[] infos = new DirectoryInfo[2];
infos[0] = new DirectoryInfo(Application.StartupPath);
infos[1] = new DirectoryInfo(@"c:\temp");
List<string> liste1 = Recherche(infos, new List<string>());//récupére une première liste
infos[1] = new DirectoryInfo(@"c:\temp2");//dans temps2 il y a le même doc que dans temp plus un second
List<string> liste2 = Recherche(infos, liste1);//récupére la deuxième liste sans doublons
infos[1] = new DirectoryInfo(@"e:\temp3");//e est un lecteur réseau
List<string> liste3 = Recherche(infos, liste2);//récupére la troisième liste sans doublons
}
public List<string> Recherche(DirectoryInfo[] infos, List<string> existants)
{
List<string> query = (from info in infos
from f in info.GetFiles()
where f.Extension ".doc" | f.Extension ".xml"
orderby f.Name //tri par le nom
select f.Name).ToList<string>();// retourne la liste de tous les doc et xml dans les répertoires contenus dans le tableau
return existants.Union(query).ToList<string>();//la méthode d'extension de classe Union (issue de Linq) permet d'unir deux collections sans doublons, m^me si l'une est vide comme c'est le cas à la première recherche
}
Rapakooti
Messages postés90Date d'inscriptionmercredi 4 décembre 2002StatutMembreDernière intervention18 mai 2018 18 nov. 2012 à 14:33
merci encore j'ai modifier ta procedure pour l'adapte ( juste extention) mais il me retourne rien sur mes lecteur reseau ,par contre effectivement autant pour moi pas de souci pour le C: je suis sous windows 8 s j'avais le soucis sous windows 7 avec directoryinfo