/// <summary> /// Builds mods from an archive. /// </summary> /// <remarks> /// If the specified archive contains mods, they are simply extracted. Otherwise, the archive /// is examined to determine if it is already in a recognized format. If not, or if the archive /// spans multiple volumes, then the archive is repackaged. /// </remarks> /// <param name="p_mfrFormats">The registry of supported mod formats.</param> /// <param name="p_strArchivePath">The archive to build into a mod.</param> /// <param name="p_dlgConfirmOverwrite">The delegate to call to resolve conflicts with existing files.</param> /// <param name="p_strMessage">The message describing the state of the task.</param> /// <returns>The paths to the new mods.</returns> /// <exception cref="ArgumentException">Thrown if the specified path is not an archive.</exception> private IList <string> DoFromArchive(IModFormatRegistry p_mfrFormats, string p_strArchivePath, ConfirmOverwriteCallback p_dlgConfirmOverwrite, out string p_strMessage) { p_strMessage = null; Trace.TraceInformation(String.Format("[{0}] Adding mod from archive.", p_strArchivePath)); if (String.IsNullOrEmpty(p_strArchivePath) || !File.Exists(p_strArchivePath) || !Archive.IsArchive(p_strArchivePath)) { throw new ArgumentException("The specified path is not an archive file.", "p_strArchivePath"); } List <string> lstFoundMods = new List <string>(); List <string> lstModsInArchive = new List <string>(); ItemMessage = "Examining archive..."; ItemProgress = 0; ItemProgressMaximum = p_mfrFormats.Formats.Count; IModFormat mftDestFormat = null; try { using (SevenZipExtractor szeExtractor = Archive.GetExtractor(p_strArchivePath)) { if (Status == TaskStatus.Cancelling) { return(lstFoundMods); } ReadOnlyCollection <string> lstArchiveFiles = szeExtractor.ArchiveFileNames; foreach (IModFormat mftFormat in p_mfrFormats.Formats) { ItemMessage = String.Format("Examining archive for {0} mods...", mftFormat.Name); lstModsInArchive.AddRange(lstArchiveFiles.Where(x => mftFormat.Extension.Equals(Path.GetExtension(x), StringComparison.OrdinalIgnoreCase))); StepItemProgress(); if (Status == TaskStatus.Cancelling) { return(lstFoundMods); } } StepOverallProgress(); } if (lstModsInArchive.Count == 0) { ItemMessage = "Determining archive format..."; ItemProgress = 0; ItemProgressMaximum = p_mfrFormats.Formats.Count; List <KeyValuePair <FormatConfidence, IModFormat> > lstFormats = new List <KeyValuePair <FormatConfidence, IModFormat> >(); foreach (IModFormat mftFormat in p_mfrFormats.Formats) { lstFormats.Add(new KeyValuePair <FormatConfidence, IModFormat>(mftFormat.CheckFormatCompliance(p_strArchivePath), mftFormat)); StepItemProgress(); if (Status == TaskStatus.Cancelling) { return(lstFoundMods); } } lstFormats.Sort((x, y) => y.Key.CompareTo(x.Key)); if ((lstFormats.Count == 0) || (lstFormats[0].Key <= FormatConfidence.Convertible)) { return(lstFoundMods); } mftDestFormat = lstFormats[0].Value; } StepOverallProgress(); } catch (Exception ex) { MessageBox.Show("An error has occured with the following archive: " + p_strArchivePath + "\n\n ERROR: " + ex.Message); return(lstFoundMods); } string strTmpPath = null; try { using (SevenZipExtractor szeExtractor = Archive.GetExtractor(p_strArchivePath)) { if ((mftDestFormat != null) && (szeExtractor.VolumeFileNames.Count > 1) || (lstModsInArchive.Count > 0)) { ItemMessage = "Extracting archive..."; ItemProgress = 0; ItemProgressMaximum = szeExtractor.ArchiveFileNames.Count; strTmpPath = FileUtility.CreateTempDirectory(); szeExtractor.FileExtractionStarted += new EventHandler <FileInfoEventArgs>(Extractor_FileExtractionStarted); szeExtractor.FileExtractionFinished += new EventHandler <FileInfoEventArgs>(Extractor_FileExtractionFinished); try { szeExtractor.ExtractArchive(strTmpPath); } catch (FileNotFoundException ex) { Status = TaskStatus.Error; p_strMessage = ex.Message; return(lstFoundMods); } for (Int32 i = 0; i < lstModsInArchive.Count; i++) { lstModsInArchive[i] = Path.Combine(strTmpPath, lstModsInArchive[i]); } } else { lstModsInArchive.Add(p_strArchivePath); } } StepOverallProgress(); if (!String.IsNullOrEmpty(strTmpPath) && (mftDestFormat != null)) { //if we have extracted the file to do format shifting if (!mftDestFormat.SupportsModCompression) { return(lstFoundMods); } ItemMessage = "Compressing mod..."; ItemProgress = 0; ItemProgressMaximum = Directory.GetFiles(strTmpPath, "*", SearchOption.AllDirectories).Length; IModCompressor mcpCompressor = mftDestFormat.GetModCompressor(EnvironmentInfo); mcpCompressor.FileCompressionFinished += new CancelEventHandler(Compressor_FileCompressionFinished); string strDest = Path.Combine(GameModeInfo.ModDirectory, Path.GetFileName(p_strArchivePath)); strDest = Path.ChangeExtension(strDest, mftDestFormat.Extension); strDest = ConfirmOverwrite(p_dlgConfirmOverwrite, strDest); if (!String.IsNullOrEmpty(strDest)) { mcpCompressor.Compress(strTmpPath, strDest); lstFoundMods.Add(strDest); } } else { ItemMessage = "Copying mods..."; ItemProgress = 0; ItemProgressMaximum = lstModsInArchive.Count; foreach (string strMod in lstModsInArchive) { if (Status == TaskStatus.Cancelling) { return(lstFoundMods); } ItemMessage = String.Format("Copying mod {0}...", Path.GetFileName(strMod)); string strDest = Path.Combine(GameModeInfo.ModDirectory, Path.GetFileName(strMod)); strDest = ConfirmOverwrite(p_dlgConfirmOverwrite, strDest); if (!String.IsNullOrEmpty(strDest)) { if (string.Equals(strMod, strDest, StringComparison.OrdinalIgnoreCase)) { throw new FileNotFoundException("You can't add a mod directly from the NMM Mods folder, please move it somewhere else before adding it to the manager!"); } File.Copy(strMod, strDest, true); lstFoundMods.Add(strDest); } StepItemProgress(); } } StepOverallProgress(); } catch (FileNotFoundException ex) { MessageBox.Show("Archive: " + p_strArchivePath + "\n\n ERROR: " + ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); return(lstFoundMods); } finally { if (!String.IsNullOrEmpty(strTmpPath)) { FileUtil.ForceDelete(strTmpPath); } } return(lstFoundMods); }