public void Init() { location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fatx16", "be", "microsoft256mb.img.lz"); filter = new LZip(); filter.Open(location); image = new ZZZRawImage(); Assert.AreEqual(true, image.Open(filter)); fs = new XboxFatPlugin(); List <Partition> partitions = Core.Partitions.GetAll(image); Assert.AreEqual(2, partitions.Count); dataPartition = partitions[1]; Errno error = fs.Mount(image, dataPartition, null, null, null); Assert.AreEqual(Errno.NoError, error); }
public void Init() { location = Path.Combine(Consts.TestFilesRoot, "filesystems", "fatx16", "le", "fatx.img.lz"); filter = new LZip(); filter.Open(location); image = new ZZZRawImage(); Assert.AreEqual(true, image.Open(filter)); fs = new XboxFatPlugin(); wholePart = new Partition { Name = "Whole device", Length = image.Info.Sectors, Size = image.Info.Sectors * image.Info.SectorSize }; Errno error = fs.Mount(image, wholePart, null, null, null); Assert.AreEqual(Errno.NoError, error); }
internal static void DoLs(LsOptions options) { DicConsole.DebugWriteLine("Ls command", "--debug={0}", options.Debug); DicConsole.DebugWriteLine("Ls command", "--verbose={0}", options.Verbose); DicConsole.DebugWriteLine("Ls command", "--input={0}", options.InputFile); FiltersList filtersList = new FiltersList(); IFilter inputFilter = filtersList.GetFilter(options.InputFile); Dictionary <string, string> parsedOptions = Options.Parse(options.Options); DicConsole.DebugWriteLine("Ls command", "Parsed options:"); foreach (KeyValuePair <string, string> parsedOption in parsedOptions) { DicConsole.DebugWriteLine("Ls command", "{0} = {1}", parsedOption.Key, parsedOption.Value); } parsedOptions.Add("debug", options.Debug.ToString()); if (inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); return; } Encoding encoding = null; if (options.EncodingName != null) { try { encoding = Claunia.Encoding.Encoding.GetEncoding(options.EncodingName); if (options.Verbose) { DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName); } } catch (ArgumentException) { DicConsole.ErrorWriteLine("Specified encoding is not supported."); return; } } PluginBase plugins = new PluginBase(); try { IMediaImage imageFormat = ImageFormat.Detect(inputFilter); if (imageFormat == null) { DicConsole.WriteLine("Image format not identified, not proceeding with analysis."); return; } if (options.Verbose) { DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id); } else { DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); } try { if (!imageFormat.Open(inputFilter)) { DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("No error given"); return; } DicConsole.DebugWriteLine("Ls command", "Correctly opened image file."); DicConsole.DebugWriteLine("Ls command", "Image without headers is {0} bytes.", imageFormat.Info.ImageSize); DicConsole.DebugWriteLine("Ls command", "Image has {0} sectors.", imageFormat.Info.Sectors); DicConsole.DebugWriteLine("Ls command", "Image identifies disk type as {0}.", imageFormat.Info.MediaType); Core.Statistics.AddMediaFormat(imageFormat.Format); Core.Statistics.AddMedia(imageFormat.Info.MediaType, false); Core.Statistics.AddFilter(inputFilter.Name); } catch (Exception ex) { DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Error: {0}", ex.Message); return; } List <Partition> partitions = Core.Partitions.GetAll(imageFormat); Core.Partitions.AddSchemesToStats(partitions); List <string> idPlugins; IReadOnlyFilesystem plugin; Errno error; if (partitions.Count == 0) { DicConsole.DebugWriteLine("Ls command", "No partitions found"); } else { DicConsole.WriteLine("{0} partitions found.", partitions.Count); for (int i = 0; i < partitions.Count; i++) { DicConsole.WriteLine(); DicConsole.WriteLine("Partition {0}:", partitions[i].Sequence); DicConsole.WriteLine("Identifying filesystem on partition"); Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]); if (idPlugins.Count == 0) { DicConsole.WriteLine("Filesystem not identified"); } else if (idPlugins.Count > 1) { DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins"); foreach (string pluginName in idPlugins) { if (plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin .GetType() .GetConstructor(Type.EmptyTypes) ?.Invoke(new object[] { }); if (fs == null) { continue; } error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions); if (error == Errno.NoError) { List <string> rootDir = new List <string>(); error = fs.ReadDir("/", out rootDir); if (error == Errno.NoError) { foreach (string entry in rootDir) { DicConsole.WriteLine("{0}", entry); } } else { DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); } Core.Statistics.AddFilesystem(fs.XmlFsType.Type); } else { DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } } } else { plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin); if (plugin == null) { continue; } DicConsole.WriteLine($"Identified by {plugin.Name}."); IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin .GetType().GetConstructor(Type.EmptyTypes) ?.Invoke(new object[] { }); if (fs == null) { continue; } error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions); if (error == Errno.NoError) { List <string> rootDir = new List <string>(); error = fs.ReadDir("/", out rootDir); if (error == Errno.NoError) { foreach (string entry in rootDir) { DicConsole.WriteLine("{0}", entry); } } else { DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); } Core.Statistics.AddFilesystem(fs.XmlFsType.Type); } else { DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } } } Partition wholePart = new Partition { Name = "Whole device", Length = imageFormat.Info.Sectors, Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize }; Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart); if (idPlugins.Count == 0) { DicConsole.WriteLine("Filesystem not identified"); } else if (idPlugins.Count > 1) { DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins"); foreach (string pluginName in idPlugins) { if (plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin .GetType().GetConstructor(Type.EmptyTypes) ?.Invoke(new object[] { }); if (fs == null) { continue; } error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions); if (error == Errno.NoError) { List <string> rootDir = new List <string>(); error = fs.ReadDir("/", out rootDir); if (error == Errno.NoError) { foreach (string entry in rootDir) { DicConsole.WriteLine("{0}", entry); } } else { DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); } Core.Statistics.AddFilesystem(fs.XmlFsType.Type); } else { DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } } } else { plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin); if (plugin != null) { DicConsole.WriteLine($"Identified by {plugin.Name}."); IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin .GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); if (fs != null) { error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions); if (error == Errno.NoError) { List <string> rootDir = new List <string>(); error = fs.ReadDir("/", out rootDir); if (error == Errno.NoError) { foreach (string entry in rootDir) { if (options.Long) { FileEntryInfo stat = new FileEntryInfo(); List <string> xattrs = new List <string>(); error = fs.Stat(entry, out stat); if (error == Errno.NoError) { DicConsole.WriteLine("{0}\t{1}\t{2} bytes\t{3}", stat.CreationTimeUtc, stat.Inode, stat.Length, entry); error = fs.ListXAttr(entry, out xattrs); if (error != Errno.NoError) { continue; } foreach (string xattr in xattrs) { byte[] xattrBuf = new byte[0]; error = fs.GetXattr(entry, xattr, ref xattrBuf); if (error == Errno.NoError) { DicConsole.WriteLine("\t\t{0}\t{1} bytes", xattr, xattrBuf.Length); } } } else { DicConsole.WriteLine("{0}", entry); } } else { DicConsole.WriteLine("{0}", entry); } } } else { DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString()); } Core.Statistics.AddFilesystem(fs.XmlFsType.Type); } else { DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } } } } catch (Exception ex) { DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}"); DicConsole.DebugWriteLine("Ls command", ex.StackTrace); } Core.Statistics.AddCommand("ls"); }
public override int Invoke(IEnumerable <string> arguments) { List <string> extra = Options.Parse(arguments); if (showHelp) { Options.WriteOptionDescriptions(CommandSet.Out); return((int)ErrorNumber.HelpRequested); } MainClass.PrintCopyright(); if (MainClass.Debug) { DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; } if (MainClass.Verbose) { DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; } Statistics.AddCommand("extract-files"); if (extra.Count > 1) { DicConsole.ErrorWriteLine("Too many arguments."); return((int)ErrorNumber.UnexpectedArgumentCount); } if (extra.Count == 0) { DicConsole.ErrorWriteLine("Missing input image."); return((int)ErrorNumber.MissingArgument); } inputFile = extra[0]; DicConsole.DebugWriteLine("Extract-Files command", "--debug={0}", MainClass.Debug); DicConsole.DebugWriteLine("Extract-Files command", "--encoding={0}", encodingName); DicConsole.DebugWriteLine("Extract-Files command", "--input={0}", inputFile); DicConsole.DebugWriteLine("Extract-Files command", "--options={0}", pluginOptions); DicConsole.DebugWriteLine("Extract-Files command", "--output={0}", outputDir); DicConsole.DebugWriteLine("Extract-Files command", "--verbose={0}", MainClass.Verbose); DicConsole.DebugWriteLine("Extract-Files command", "--xattrs={0}", extractXattrs); FiltersList filtersList = new FiltersList(); IFilter inputFilter = filtersList.GetFilter(inputFile); Dictionary <string, string> parsedOptions = Core.Options.Parse(pluginOptions); DicConsole.DebugWriteLine("Extract-Files command", "Parsed options:"); foreach (KeyValuePair <string, string> parsedOption in parsedOptions) { DicConsole.DebugWriteLine("Extract-Files command", "{0} = {1}", parsedOption.Key, parsedOption.Value); } parsedOptions.Add("debug", MainClass.Debug.ToString()); if (inputFilter == null) { DicConsole.ErrorWriteLine("Cannot open specified file."); return((int)ErrorNumber.CannotOpenFile); } Encoding encoding = null; if (encodingName != null) { try { encoding = Claunia.Encoding.Encoding.GetEncoding(encodingName); if (MainClass.Verbose) { DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName); } } catch (ArgumentException) { DicConsole.ErrorWriteLine("Specified encoding is not supported."); return((int)ErrorNumber.EncodingUnknown); } } PluginBase plugins = GetPluginBase.Instance; try { IMediaImage imageFormat = ImageFormat.Detect(inputFilter); if (imageFormat == null) { DicConsole.WriteLine("Image format not identified, not proceeding with analysis."); return((int)ErrorNumber.UnrecognizedFormat); } if (MainClass.Verbose) { DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id); } else { DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name); } if (outputDir == null) { DicConsole.WriteLine("Output directory missing."); return((int)ErrorNumber.MissingArgument); } if (Directory.Exists(outputDir) || File.Exists(outputDir)) { DicConsole.ErrorWriteLine("Destination exists, aborting."); return((int)ErrorNumber.DestinationExists); } Directory.CreateDirectory(outputDir); try { if (!imageFormat.Open(inputFilter)) { DicConsole.WriteLine("Unable to open image format"); DicConsole.WriteLine("No error given"); return((int)ErrorNumber.CannotOpenFormat); } DicConsole.DebugWriteLine("Extract-Files command", "Correctly opened image file."); DicConsole.DebugWriteLine("Extract-Files command", "Image without headers is {0} bytes.", imageFormat.Info.ImageSize); DicConsole.DebugWriteLine("Extract-Files command", "Image has {0} sectors.", imageFormat.Info.Sectors); DicConsole.DebugWriteLine("Extract-Files command", "Image identifies disk type as {0}.", imageFormat.Info.MediaType); Statistics.AddMediaFormat(imageFormat.Format); Statistics.AddMedia(imageFormat.Info.MediaType, false); Statistics.AddFilter(inputFilter.Name); } catch (Exception ex) { DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("Error: {0}", ex.Message); return((int)ErrorNumber.CannotOpenFormat); } List <Partition> partitions = Core.Partitions.GetAll(imageFormat); Core.Partitions.AddSchemesToStats(partitions); List <string> idPlugins; IReadOnlyFilesystem plugin; Errno error; if (partitions.Count == 0) { DicConsole.DebugWriteLine("Extract-Files command", "No partitions found"); } else { DicConsole.WriteLine("{0} partitions found.", partitions.Count); for (int i = 0; i < partitions.Count; i++) { DicConsole.WriteLine(); DicConsole.WriteLine("Partition {0}:", partitions[i].Sequence); DicConsole.WriteLine("Identifying filesystem on partition"); Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]); if (idPlugins.Count == 0) { DicConsole.WriteLine("Filesystem not identified"); } else if (idPlugins.Count > 1) { DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins"); foreach (string pluginName in idPlugins) { if (plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin .GetType() .GetConstructor(Type.EmptyTypes) ?.Invoke(new object[] { }); error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions, @namespace); if (error == Errno.NoError) { string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME" : fs.XmlFsType.VolumeName; ExtractFilesInDir("/", fs, volumeName); Statistics.AddFilesystem(fs.XmlFsType.Type); } else { DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } } } else { plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin); DicConsole.WriteLine($"Identified by {plugin.Name}."); IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin .GetType().GetConstructor(Type.EmptyTypes) ?.Invoke(new object[] { }); error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions, @namespace); if (error == Errno.NoError) { string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME" : fs.XmlFsType.VolumeName; ExtractFilesInDir("/", fs, volumeName); Statistics.AddFilesystem(fs.XmlFsType.Type); } else { DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } } } Partition wholePart = new Partition { Name = "Whole device", Length = imageFormat.Info.Sectors, Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize }; Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart); if (idPlugins.Count == 0) { DicConsole.WriteLine("Filesystem not identified"); } else if (idPlugins.Count > 1) { DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins"); foreach (string pluginName in idPlugins) { if (plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin)) { DicConsole.WriteLine($"As identified by {plugin.Name}."); IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin .GetType().GetConstructor(Type.EmptyTypes) ?.Invoke(new object[] { }); error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions, @namespace); if (error == Errno.NoError) { string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME" : fs.XmlFsType.VolumeName; ExtractFilesInDir("/", fs, volumeName); Statistics.AddFilesystem(fs.XmlFsType.Type); } else { DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } } } else { plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin); DicConsole.WriteLine($"Identified by {plugin.Name}."); IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions, @namespace); if (error == Errno.NoError) { string volumeName = string.IsNullOrEmpty(fs.XmlFsType.VolumeName) ? "NO NAME" : fs.XmlFsType.VolumeName; ExtractFilesInDir("/", fs, volumeName); Statistics.AddFilesystem(fs.XmlFsType.Type); } else { DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString()); } } } catch (Exception ex) { DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}"); DicConsole.DebugWriteLine("Extract-Files command", ex.StackTrace); return((int)ErrorNumber.UnexpectedException); } return((int)ErrorNumber.NoError); }
protected void OnMenuOpen(object sender, EventArgs e) { // TODO: Extensions OpenFileDialog dlgOpenImage = new OpenFileDialog { Title = "Choose image to open" }; DialogResult result = dlgOpenImage.ShowDialog(this); if (result != DialogResult.Ok) { return; } FiltersList filtersList = new FiltersList(); IFilter inputFilter = filtersList.GetFilter(dlgOpenImage.FileName); if (inputFilter == null) { MessageBox.Show("Cannot open specified file.", MessageBoxType.Error); return; } try { IMediaImage imageFormat = ImageFormat.Detect(inputFilter); if (imageFormat == null) { MessageBox.Show("Image format not identified.", MessageBoxType.Error); return; } DicConsole.WriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id); try { if (!imageFormat.Open(inputFilter)) { MessageBox.Show("Unable to open image format", MessageBoxType.Error); DicConsole.ErrorWriteLine("Unable to open image format"); DicConsole.ErrorWriteLine("No error given"); return; } // TODO: SVG Stream logo = ResourceHandler .GetResourceStream($"DiscImageChef.Gui.Assets.Logos.Media.{imageFormat.Info.MediaType}.png"); TreeGridItem imageGridItem = new TreeGridItem { Values = new object[] { logo == null ? null : new Bitmap(logo), $"{Path.GetFileName(dlgOpenImage.FileName)} ({imageFormat.Info.MediaType})", dlgOpenImage.FileName, new pnlImageInfo(dlgOpenImage.FileName, inputFilter, imageFormat), inputFilter, imageFormat } }; List <Partition> partitions = Core.Partitions.GetAll(imageFormat); Core.Partitions.AddSchemesToStats(partitions); bool checkraw = false; List <string> idPlugins; IFilesystem plugin; PluginBase plugins = GetPluginBase.Instance; if (partitions.Count == 0) { DicConsole.DebugWriteLine("Analyze command", "No partitions found"); checkraw = true; } else { DicConsole.WriteLine("{0} partitions found.", partitions.Count); foreach (string scheme in partitions.Select(p => p.Scheme).Distinct().OrderBy(s => s)) { TreeGridItem schemeGridItem = new TreeGridItem { Values = new object[] { nullImage, // TODO: Add icons to partition schemes scheme } }; foreach (Partition partition in partitions .Where(p => p.Scheme == scheme).OrderBy(p => p.Start)) { TreeGridItem partitionGridItem = new TreeGridItem { Values = new object[] { nullImage, // TODO: Add icons to partition schemes $"{partition.Name} ({partition.Type})", null, new pnlPartition(partition) } }; DicConsole.WriteLine("Identifying filesystem on partition"); Core.Filesystems.Identify(imageFormat, out idPlugins, partition); if (idPlugins.Count == 0) { DicConsole.WriteLine("Filesystem not identified"); } else { DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins"); foreach (string pluginName in idPlugins) { if (plugins.PluginsList.TryGetValue(pluginName, out plugin)) { plugin.GetInformation(imageFormat, partition, out string information, null); IReadOnlyFilesystem fsPlugin = plugin as IReadOnlyFilesystem; if (fsPlugin != null) { Errno error = fsPlugin.Mount(imageFormat, partition, null, new Dictionary <string, string>(), null); if (error != Errno.NoError) { fsPlugin = null; } } TreeGridItem filesystemGridItem = new TreeGridItem { Values = new object[] { nullImage, // TODO: Add icons to filesystems plugin.XmlFsType.VolumeName is null ? $"{plugin.XmlFsType.Type}" : $"{plugin.XmlFsType.VolumeName} ({plugin.XmlFsType.Type})", fsPlugin, new pnlFilesystem(plugin.XmlFsType, information) } }; if (fsPlugin != null) { Statistics.AddCommand("ls"); filesystemGridItem.Children.Add(placeholderItem); } Statistics.AddFilesystem(plugin.XmlFsType.Type); partitionGridItem.Children.Add(filesystemGridItem); } } } schemeGridItem.Children.Add(partitionGridItem); } imageGridItem.Children.Add(schemeGridItem); } } if (checkraw) { Partition wholePart = new Partition { Name = "Whole device", Length = imageFormat.Info.Sectors, Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize }; Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart); if (idPlugins.Count == 0) { DicConsole.WriteLine("Filesystem not identified"); } else { DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins"); foreach (string pluginName in idPlugins) { if (plugins.PluginsList.TryGetValue(pluginName, out plugin)) { plugin.GetInformation(imageFormat, wholePart, out string information, null); IReadOnlyFilesystem fsPlugin = plugin as IReadOnlyFilesystem; if (fsPlugin != null) { Errno error = fsPlugin.Mount(imageFormat, wholePart, null, new Dictionary <string, string>(), null); if (error != Errno.NoError) { fsPlugin = null; } } TreeGridItem filesystemGridItem = new TreeGridItem { Values = new object[] { nullImage, // TODO: Add icons to filesystems plugin.XmlFsType.VolumeName is null ? $"{plugin.XmlFsType.Type}" : $"{plugin.XmlFsType.VolumeName} ({plugin.XmlFsType.Type})", fsPlugin, new pnlFilesystem(plugin.XmlFsType, information) } }; if (fsPlugin != null) { Statistics.AddCommand("ls"); filesystemGridItem.Children.Add(placeholderItem); } Statistics.AddFilesystem(plugin.XmlFsType.Type); imageGridItem.Children.Add(filesystemGridItem); } } } } imagesRoot.Children.Add(imageGridItem); treeImages.ReloadData(); Statistics.AddMediaFormat(imageFormat.Format); Statistics.AddMedia(imageFormat.Info.MediaType, false); Statistics.AddFilter(inputFilter.Name); }