Naposledy aktivní 1777326157

Revize 6df04f018fe6a3a8b52c5150a6e726fbde62ae87

gistfile1.txt Raw
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.IO;
5using System.Linq;
6using System.Text;
7using Microsoft.Win32;
8
9namespace DiskUsageLog
10{
11 class Program
12 {
13 const long ONE_GB = 1024L * 1024 * 1024;
14 const long ONE_MB = 1024L * 1024;
15
16 static readonly string[] HardExcludedFolders =
17 {
18 "WinSxS",
19 "Microsoft.NET",
20 "assembly"
21 };
22
23 static readonly string InstallerPath = @"C:\Windows\Installer";
24
25 static readonly string[] KnownCacheFolderNames =
26 {
27 "Temp", "tmp", "Logs", "LogFiles",
28 "INetCache", "Temporary Internet Files",
29 "WER", "CrashDumps"
30 };
31
32 static Dictionary<string, ExtensionStat> ExtensionStats =
33 new Dictionary<string, ExtensionStat>(StringComparer.OrdinalIgnoreCase);
34
35 static List<FileInfo> LargestFiles = new List<FileInfo>();
36 static List<LargeFolder> LargeFolders = new List<LargeFolder>();
37 static List<FileInfo> StaleFiles = new List<FileInfo>();
38 static List<LargeFolder> RootBreakdown = new List<LargeFolder>();
39 static List<CacheFolder> DetectedCacheFolders = new List<CacheFolder>();
40 static List<LargeFolder> SystemDiagResults = new List<LargeFolder>();
41
42 static long TotalFilesScanned;
43 static long TotalFoldersScanned;
44 static long TotalErrorCount;
45 static long TotalSizeScanned;
46
47 static Stopwatch Timer = new Stopwatch();
48 static int spinnerIndex;
49 static readonly char[] SpinnerChars = { '|', '/', '-', '\\' };
50
51 static void Main(string[] args)
52 {
53 Console.OutputEncoding = System.Text.Encoding.UTF8;
54
55 string rootPath = args.Length > 0 ? args[0] : @"C:\";
56
57 if (!Directory.Exists(rootPath))
58 {
59 Console.WriteLine("Chemin invalide.");
60 return;
61 }
62
63 Console.WriteLine("DiskUsageLog - Analyse disque");
64 Console.WriteLine("Racine analysée : " + rootPath);
65 DisplayXstoreInfo();
66 Console.WriteLine("--------------------------------------------------\n");
67
68 Timer.Start();
69
70 string[] rootDirs;
71 try { rootDirs = Directory.GetDirectories(rootPath); }
72 catch { rootDirs = new string[0]; }
73
74 foreach (string dir in rootDirs)
75 {
76 long size = AnalyzeDirectory(dir);
77 RootBreakdown.Add(new LargeFolder
78 {
79 Path = dir,
80 Size = size
81 });
82 }
83
84 ClearProgress();
85 Timer.Stop();
86
87 DisplaySummary();
88 DisplayRootBreakdown();
89 DisplayLargeFolders();
90 DisplayTopExtensions();
91 DisplayLargestFiles();
92 DisplayStaleFiles();
93 DisplayCacheFolders();
94 DisplaySystemDiagnostic();
95 DisplayOrphanInstallers();
96
97 ExportReport(rootPath);
98
99 Console.WriteLine("\nAnalyse terminée.");
100 }
101
102 // ======================= ANALYSE =======================
103
104 static long AnalyzeDirectory(string path)
105 {
106 long totalSize = 0;
107 TotalFoldersScanned++;
108
109 string folderName = Path.GetFileName(path);
110 bool isKnownCache = KnownCacheFolderNames.Any(c =>
111 c.Equals(folderName, StringComparison.OrdinalIgnoreCase));
112
113 try
114 {
115 foreach (string file in Directory.GetFiles(path))
116 {
117 FileInfo fi = new FileInfo(file);
118 totalSize += fi.Length;
119 TotalFilesScanned++;
120 TotalSizeScanned += fi.Length;
121
122 bool excluded = IsExcludedFile(fi, path);
123
124 if (!IsSystemCritical(path) && !excluded)
125 TrackExtension(fi);
126
127 if (!excluded)
128 {
129 TrackLargestFiles(fi);
130 TrackStaleFiles(fi);
131 }
132 }
133
134 if (TotalFoldersScanned % 100 == 0)
135 UpdateProgress(path);
136
137 foreach (string dir in Directory.GetDirectories(path))
138 {
139 if (IsHardExcluded(dir)) continue;
140 totalSize += AnalyzeDirectory(dir);
141 }
142 }
143 catch
144 {
145 TotalErrorCount++;
146 }
147
148 if (isKnownCache && totalSize >= 50 * ONE_MB)
149 {
150 DetectedCacheFolders.Add(new CacheFolder
151 {
152 Path = path,
153 Size = totalSize,
154 FolderName = folderName
155 });
156 }
157
158 if (totalSize >= ONE_GB)
159 {
160 LargeFolders.Add(new LargeFolder
161 {
162 Path = path,
163 Size = totalSize,
164 IsRiskArea = IsRiskArea(path)
165 });
166 }
167
168 return totalSize;
169 }
170
171 // ======================= REGLES =======================
172
173 static bool IsHardExcluded(string path)
174 {
175 string name = Path.GetFileName(path);
176 return HardExcludedFolders.Any(e =>
177 e.Equals(name, StringComparison.OrdinalIgnoreCase));
178 }
179
180 static bool IsSystemCritical(string path)
181 {
182 return path.StartsWith(@"C:\Windows\System32",
183 StringComparison.OrdinalIgnoreCase);
184 }
185
186 static bool IsRiskArea(string path)
187 {
188 return path.StartsWith(@"C:\Windows\Installer", StringComparison.OrdinalIgnoreCase)
189 || path.StartsWith(@"C:\Windows\Temp", StringComparison.OrdinalIgnoreCase)
190 || path.StartsWith(@"C:\Windows\SoftwareDistribution", StringComparison.OrdinalIgnoreCase)
191 || path.Contains(@"\AppData\Local\Temp");
192 }
193
194 // ======================= EXCLUSIONS =======================
195
196 static bool IsExcludedFile(FileInfo fi, string dirPath)
197 {
198 if (fi.Extension.Equals(".dbf", StringComparison.OrdinalIgnoreCase)
199 && dirPath.StartsWith(@"C:\xstoredb", StringComparison.OrdinalIgnoreCase))
200 return true;
201
202 return false;
203 }
204
205 // ======================= EXTENSIONS =======================
206
207 static void TrackExtension(FileInfo fi)
208 {
209 string ext = string.IsNullOrEmpty(fi.Extension)
210 ? "[sans_ext]"
211 : fi.Extension.ToLower();
212
213 if (!ExtensionStats.ContainsKey(ext))
214 ExtensionStats[ext] = new ExtensionStat();
215
216 ExtensionStats[ext].Count++;
217 ExtensionStats[ext].Size += fi.Length;
218 }
219
220 static void DisplayTopExtensions()
221 {
222 Console.WriteLine("\n=== TOP 20 EXTENSIONS (hors système critique) ===\n");
223 Console.WriteLine("{0,-12} {1,10} {2,15}",
224 "Extension", "Fichiers", "Taille (GB)");
225
226 foreach (var ext in ExtensionStats
227 .OrderByDescending(e => e.Value.Size)
228 .Take(20))
229 {
230 Console.WriteLine("{0,-12} {1,10} {2,15}",
231 ext.Key,
232 ext.Value.Count,
233 ToGB(ext.Value.Size));
234 }
235 }
236
237 // ======================= GROS FICHIERS =======================
238
239 static void TrackLargestFiles(FileInfo fi)
240 {
241 LargestFiles.Add(fi);
242 LargestFiles = LargestFiles
243 .OrderByDescending(f => f.Length)
244 .Take(10)
245 .ToList();
246 }
247
248 static void DisplayLargestFiles()
249 {
250 Console.WriteLine("\n=== TOP 10 PLUS GROS FICHIERS ===\n");
251
252 foreach (FileInfo fi in LargestFiles)
253 {
254 Console.WriteLine("{0} : {1} GB",
255 fi.FullName,
256 ToGB(fi.Length));
257 }
258 }
259
260 // ======================= DOSSIERS =======================
261
262 static void DisplayLargeFolders()
263 {
264 Console.WriteLine("\n=== DOSSIERS > 1 Go ===\n");
265
266 foreach (LargeFolder f in LargeFolders
267 .OrderByDescending(f => f.Size))
268 {
269 string flag = f.IsRiskArea ? " !!!" : "";
270 Console.WriteLine("{0} : {1} GB{2}",
271 f.Path,
272 ToGB(f.Size),
273 flag);
274 }
275
276 Console.WriteLine("\n!!! = zone connue à dérive disque");
277 }
278
279 // ======================= MSI ORPHELINS =======================
280
281 static void DisplayOrphanInstallers()
282 {
283 Console.WriteLine("\n=== MSI / MSP ORPHELINS POTENTIELS ===\n");
284
285 if (!Directory.Exists(InstallerPath))
286 {
287 Console.WriteLine("Répertoire Windows Installer introuvable.");
288 return;
289 }
290
291 var allInstallers = GetInstallerFiles();
292 var referencedInstallers = GetReferencedInstallerFiles();
293
294 var orphans = allInstallers.Values
295 .Where(f => !referencedInstallers.Contains(f.FullName))
296 .OrderByDescending(f => f.Length)
297 .ToList();
298
299 long total = 0;
300
301 foreach (var fi in orphans)
302 {
303 Console.WriteLine("{0,-20} {1,10} GB",
304 fi.Name,
305 ToGB(fi.Length));
306
307 total += fi.Length;
308 }
309
310 Console.WriteLine("\nTotal récupérable potentiel : {0} GB",
311 ToGB(total));
312
313 Console.WriteLine(
314 "\nATTENTION : aucune suppression automatique.\nAnalyse uniquement.");
315 }
316
317 static Dictionary<string, FileInfo> GetInstallerFiles()
318 {
319 var dict = new Dictionary<string, FileInfo>(
320 StringComparer.OrdinalIgnoreCase);
321
322 try
323 {
324 foreach (string file in Directory.GetFiles(InstallerPath))
325 {
326 if (file.EndsWith(".msi", StringComparison.OrdinalIgnoreCase) ||
327 file.EndsWith(".msp", StringComparison.OrdinalIgnoreCase))
328 {
329 FileInfo fi = new FileInfo(file);
330 dict[fi.FullName] = fi;
331 }
332 }
333 }
334 catch
335 {
336 // Accès refusé
337 }
338
339 return dict;
340 }
341
342 static HashSet<string> GetReferencedInstallerFiles()
343 {
344 var result = new HashSet<string>(
345 StringComparer.OrdinalIgnoreCase);
346
347 ReadInstallerRegistry(
348 @"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData",
349 result);
350
351 ReadInstallerRegistry(
352 @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Installer\UserData",
353 result);
354
355 return result;
356 }
357
358 static void ReadInstallerRegistry(string baseKey, HashSet<string> result)
359 {
360 try
361 {
362 using (RegistryKey root =
363 Registry.LocalMachine.OpenSubKey(baseKey))
364 {
365 if (root == null) return;
366
367 foreach (string sid in root.GetSubKeyNames())
368 {
369 using (RegistryKey products =
370 root.OpenSubKey(sid + @"\Products"))
371 {
372 if (products == null) continue;
373
374 foreach (string prod in products.GetSubKeyNames())
375 {
376 using (RegistryKey installProps =
377 products.OpenSubKey(prod + @"\InstallProperties"))
378 {
379 if (installProps == null) continue;
380
381 string localPackage =
382 installProps.GetValue("LocalPackage") as string;
383
384 if (!string.IsNullOrEmpty(localPackage))
385 result.Add(localPackage);
386 }
387 }
388 }
389 }
390 }
391 }
392 catch
393 {
394 // erreur registre
395 }
396 }
397
398 // ======================= PROGRESSION =======================
399
400 static void UpdateProgress(string currentDir)
401 {
402 spinnerIndex = (spinnerIndex + 1) % SpinnerChars.Length;
403 string dir = currentDir.Length > 50
404 ? "..." + currentDir.Substring(currentDir.Length - 47)
405 : currentDir;
406
407 string line = string.Format("\r {0} {1:N0} fichiers | {2:N0} dossiers | {3} GB | {4}",
408 SpinnerChars[spinnerIndex],
409 TotalFilesScanned,
410 TotalFoldersScanned,
411 ToGB(TotalSizeScanned),
412 dir);
413
414 int width = 120;
415 try { width = Console.WindowWidth; } catch { }
416 if (line.Length < width)
417 line = line.PadRight(width - 1);
418 else if (line.Length >= width)
419 line = line.Substring(0, width - 1);
420
421 Console.Write(line);
422 }
423
424 static void ClearProgress()
425 {
426 int width = 120;
427 try { width = Console.WindowWidth; } catch { }
428 Console.Write("\r" + new string(' ', width - 1) + "\r");
429 }
430
431 // ======================= RESUME =======================
432
433 static void DisplaySummary()
434 {
435 Console.WriteLine("\n=== RESUME DU SCAN ===\n");
436 Console.WriteLine("Machine : {0}", Environment.MachineName);
437 Console.WriteLine("Duree : {0}", Timer.Elapsed.ToString(@"hh\:mm\:ss"));
438 Console.WriteLine("Fichiers analyses : {0:N0}", TotalFilesScanned);
439 Console.WriteLine("Dossiers analyses : {0:N0}", TotalFoldersScanned);
440 Console.WriteLine("Taille totale scannee : {0} GB", ToGB(TotalSizeScanned));
441 Console.WriteLine("Erreurs (acces refuse) : {0:N0}", TotalErrorCount);
442 }
443
444 // ======================= ARBORESCENCE RACINE =======================
445
446 static void DisplayRootBreakdown()
447 {
448 Console.WriteLine("\n=== REPARTITION RACINE (top 30) ===\n");
449
450 foreach (var item in RootBreakdown.OrderByDescending(r => r.Size).Take(30))
451 {
452 string name = Path.GetFileName(item.Path);
453 if (string.IsNullOrEmpty(name)) name = item.Path;
454
455 double pct = TotalSizeScanned > 0
456 ? (item.Size * 100.0 / TotalSizeScanned)
457 : 0;
458
459 int barLen = Math.Min((int)(pct / 2), 25);
460 string bar = new string('#', barLen).PadRight(25);
461
462 Console.WriteLine("{0,-40} {1,8} GB [{2}] {3,5:F1}%",
463 name.Length > 40 ? name.Substring(0, 37) + "..." : name,
464 ToGB(item.Size),
465 bar,
466 pct);
467 }
468 }
469
470 // ======================= FICHIERS ANCIENS =======================
471
472 static void TrackStaleFiles(FileInfo fi)
473 {
474 try
475 {
476 if (fi.Length < 100 * ONE_MB) return;
477 if (fi.LastWriteTime > DateTime.Now.AddYears(-2)) return;
478
479 StaleFiles.Add(fi);
480 StaleFiles = StaleFiles
481 .OrderByDescending(f => f.Length)
482 .Take(20)
483 .ToList();
484 }
485 catch { }
486 }
487
488 static void DisplayStaleFiles()
489 {
490 if (StaleFiles.Count == 0) return;
491
492 Console.WriteLine("\n=== GROS FICHIERS ANCIENS (>100 Mo, non modifies depuis 2+ ans) ===\n");
493
494 foreach (var fi in StaleFiles)
495 {
496 string path = fi.FullName.Length > 75
497 ? "..." + fi.FullName.Substring(fi.FullName.Length - 72)
498 : fi.FullName;
499
500 Console.WriteLine("{0,-75} {1,8} GB {2:yyyy-MM-dd}",
501 path, ToGB(fi.Length), fi.LastWriteTime);
502 }
503 }
504
505 // ======================= DOSSIERS TEMPORAIRES =======================
506
507 static void DisplayCacheFolders()
508 {
509 if (DetectedCacheFolders.Count == 0) return;
510
511 Console.WriteLine("\n=== DOSSIERS TEMPORAIRES / LOGS DETECTES (>50 Mo) ===\n");
512
513 long total = 0;
514 foreach (var cf in DetectedCacheFolders.OrderByDescending(c => c.Size).Take(30))
515 {
516 string path = cf.Path.Length > 70
517 ? "..." + cf.Path.Substring(cf.Path.Length - 67)
518 : cf.Path;
519
520 Console.WriteLine("{0,-70} {1,8} GB",
521 path, ToGB(cf.Size));
522 total += cf.Size;
523 }
524
525 Console.WriteLine("\nTotal temporaires/logs : {0} GB", ToGB(total));
526 }
527
528 // ======================= DIAGNOSTIC SYSTEME =======================
529
530 static void DisplaySystemDiagnostic()
531 {
532 Console.WriteLine("\n=== DIAGNOSTIC ZONES SYSTEME ===\n");
533
534 var zones = new List<string>
535 {
536 @"C:\Windows\SoftwareDistribution\Download",
537 @"C:\Windows\Temp",
538 @"C:\Windows\Logs",
539 @"C:\Windows\Panther",
540 @"C:\ProgramData\Microsoft\Windows\WER",
541 @"C:\$Recycle.Bin"
542 };
543
544 // Temp + cache par profil utilisateur
545 try
546 {
547 foreach (string userDir in Directory.GetDirectories(@"C:\Users"))
548 {
549 string userName = Path.GetFileName(userDir);
550 if (userName.Equals("Public", StringComparison.OrdinalIgnoreCase)
551 || userName.Equals("Default", StringComparison.OrdinalIgnoreCase)
552 || userName.Equals("Default User", StringComparison.OrdinalIgnoreCase))
553 continue;
554
555 zones.Add(Path.Combine(userDir, @"AppData\Local\Temp"));
556 zones.Add(Path.Combine(userDir, @"AppData\Local\Microsoft\Windows\INetCache"));
557
558 // Firefox cache
559 string firefoxProfiles = Path.Combine(userDir, @"AppData\Local\Mozilla\Firefox\Profiles");
560 if (Directory.Exists(firefoxProfiles))
561 {
562 foreach (string profile in Directory.GetDirectories(firefoxProfiles))
563 zones.Add(Path.Combine(profile, "cache2"));
564 }
565 }
566 }
567 catch { }
568
569 // memory.dmp
570 string memDump = @"C:\Windows\memory.dmp";
571 if (File.Exists(memDump))
572 {
573 long dumpSize = new FileInfo(memDump).Length;
574 SystemDiagResults.Add(new LargeFolder { Path = memDump, Size = dumpSize });
575 Console.WriteLine("{0,-65} {1,8} GB", memDump, ToGB(dumpSize));
576 }
577
578 long grandTotal = 0;
579 foreach (string zone in zones)
580 {
581 if (!Directory.Exists(zone)) continue;
582 long size = GetDirectorySize(zone);
583 if (size < ONE_MB) continue;
584
585 SystemDiagResults.Add(new LargeFolder { Path = zone, Size = size });
586 Console.WriteLine("{0,-65} {1,8} GB",
587 zone.Length > 65 ? "..." + zone.Substring(zone.Length - 62) : zone,
588 ToGB(size));
589 grandTotal += size;
590 }
591
592 Console.WriteLine("\nTotal zones systeme recuperable : {0} GB", ToGB(grandTotal));
593 }
594
595 static long GetDirectorySize(string path)
596 {
597 long size = 0;
598 try
599 {
600 foreach (string file in Directory.GetFiles(path))
601 {
602 try { size += new FileInfo(file).Length; } catch { }
603 }
604 foreach (string dir in Directory.GetDirectories(path))
605 {
606 size += GetDirectorySize(dir);
607 }
608 }
609 catch { }
610 return size;
611 }
612
613 // ======================= EXPORT =======================
614
615 static void ExportReport(string rootPath)
616 {
617 string fileName = Environment.MachineName + ".diskusage.log";
618 string exeDir = AppDomain.CurrentDomain.BaseDirectory;
619 string exportPath = Path.Combine(exeDir, fileName);
620
621 try
622 {
623 var sb = new StringBuilder();
624 sb.AppendLine("DiskUsageLog - Rapport d'analyse disque");
625 sb.AppendLine("Machine : " + Environment.MachineName);
626 sb.AppendLine("Racine : " + rootPath);
627 sb.AppendLine("Date : " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
628 sb.AppendLine("Duree : " + Timer.Elapsed.ToString(@"hh\:mm\:ss"));
629 sb.AppendLine(new string('=', 80));
630
631 sb.AppendFormat("\nFichiers analyses : {0:N0}\n", TotalFilesScanned);
632 sb.AppendFormat("Dossiers analyses : {0:N0}\n", TotalFoldersScanned);
633 sb.AppendFormat("Taille totale : {0} GB\n", ToGB(TotalSizeScanned));
634 sb.AppendFormat("Erreurs : {0:N0}\n", TotalErrorCount);
635
636 sb.AppendLine("\n--- REPARTITION RACINE ---");
637 foreach (var item in RootBreakdown.OrderByDescending(r => r.Size).Take(30))
638 {
639 string name = Path.GetFileName(item.Path);
640 if (string.IsNullOrEmpty(name)) name = item.Path;
641 sb.AppendFormat("{0,-60} {1} GB\n", name, ToGB(item.Size));
642 }
643
644 sb.AppendLine("\n--- DOSSIERS > 1 Go ---");
645 foreach (var f in LargeFolders.OrderByDescending(f => f.Size))
646 {
647 string flag = f.IsRiskArea ? " !!!" : "";
648 sb.AppendFormat("{0} : {1} GB{2}\n", f.Path, ToGB(f.Size), flag);
649 }
650
651 sb.AppendLine("\n--- TOP 20 EXTENSIONS ---");
652 foreach (var ext in ExtensionStats.OrderByDescending(e => e.Value.Size).Take(20))
653 {
654 sb.AppendFormat("{0,-12} {1,10} fichiers {2} GB\n",
655 ext.Key, ext.Value.Count, ToGB(ext.Value.Size));
656 }
657
658 sb.AppendLine("\n--- TOP 10 PLUS GROS FICHIERS ---");
659 foreach (var fi in LargestFiles)
660 sb.AppendFormat("{0} : {1} GB\n", fi.FullName, ToGB(fi.Length));
661
662 if (StaleFiles.Count > 0)
663 {
664 sb.AppendLine("\n--- GROS FICHIERS ANCIENS ---");
665 foreach (var fi in StaleFiles)
666 sb.AppendFormat("{0} : {1} GB (modifie {2:yyyy-MM-dd})\n",
667 fi.FullName, ToGB(fi.Length), fi.LastWriteTime);
668 }
669
670 if (DetectedCacheFolders.Count > 0)
671 {
672 sb.AppendLine("\n--- DOSSIERS TEMPORAIRES / LOGS ---");
673 foreach (var cf in DetectedCacheFolders.OrderByDescending(c => c.Size).Take(30))
674 sb.AppendFormat("{0} : {1} GB\n", cf.Path, ToGB(cf.Size));
675 }
676
677 if (SystemDiagResults.Count > 0)
678 {
679 sb.AppendLine("\n--- DIAGNOSTIC ZONES SYSTEME ---");
680 foreach (var sd in SystemDiagResults.OrderByDescending(s => s.Size))
681 sb.AppendFormat("{0} : {1} GB\n", sd.Path, ToGB(sd.Size));
682 }
683
684 File.WriteAllText(exportPath, sb.ToString());
685 Console.WriteLine("\nRapport exporte : " + exportPath);
686 }
687 catch (Exception ex)
688 {
689 Console.WriteLine("\nErreur export : " + ex.Message);
690 }
691 }
692
693 // ======================= UTILS =======================
694
695 static double ToGB(long bytes)
696 {
697 return Math.Round(bytes / 1024d / 1024 / 1024, 2);
698 }
699
700 static void DisplayXstoreInfo()
701 {
702 try
703 {
704 using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\GFI"))
705 {
706 if (key == null) return;
707
708 Console.WriteLine(" --- XSTORE ---");
709
710 foreach (var name in key.GetValueNames())
711 {
712 var val = key.GetValue(name);
713 if (val != null && val.ToString().Length > 0)
714 Console.WriteLine($" {name,-25}: {val}");
715 }
716 }
717 }
718 catch { }
719 }
720 }
721
722 // ======================= MODELES =======================
723
724 class ExtensionStat
725 {
726 public int Count;
727 public long Size;
728 }
729
730 class LargeFolder
731 {
732 public string Path;
733 public long Size;
734 public bool IsRiskArea;
735 }
736
737 class CacheFolder
738 {
739 public string Path;
740 public long Size;
741 public string FolderName;
742 }
743}