Upgrade SevenZipExtractor, fix for bad zips, add Ignore Missing Files button

This commit is contained in:
Timothy Baldridge 2019-08-07 17:06:38 -06:00
parent 687b920c85
commit 8513441afd
21 changed files with 294 additions and 180 deletions

View File

@ -32,6 +32,26 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />

View File

@ -31,6 +31,24 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="K4os.Compression.LZ4, Version=1.1.11.0, Culture=neutral, PublicKeyToken=2186fa9121ef231d, processorArchitecture=MSIL">
<HintPath>..\packages\K4os.Compression.LZ4.1.1.11\lib\net46\K4os.Compression.LZ4.dll</HintPath>

BIN
SevenZipExtractor/7z.dll.gz Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -97,48 +97,6 @@ namespace SevenZipExtractor
});
}
public void Extract(Func<Entry, Stream> getOutputStream, bool leave_open = false)
{
IList<Stream> fileStreams = new List<Stream>();
try
{
foreach (Entry entry in Entries)
{
Stream outputStream = getOutputStream(entry);
if (outputStream == null) // outputStream = null means SKIP
{
fileStreams.Add(null);
continue;
}
if (entry.IsFolder)
{
fileStreams.Add(null);
continue;
}
fileStreams.Add(outputStream);
}
this.archive.Extract(null, 0xFFFFFFFF, 0, new ArchiveStreamsCallback(fileStreams));
}
finally
{
if (!leave_open)
{
foreach (Stream stream in fileStreams)
{
if (stream != null)
{
stream.Dispose();
}
}
}
}
}
public void Extract(Func<Entry, string> getOutputPath)
{
IList<Stream> fileStreams = new List<Stream>();
@ -186,6 +144,48 @@ namespace SevenZipExtractor
}
}
public void Extract(Func<Entry, Stream> getOutputStream, bool leave_open = false)
{
IList<Stream> fileStreams = new List<Stream>();
try
{
foreach (Entry entry in Entries)
{
Stream outputStream = getOutputStream(entry);
if (outputStream == null) // outputStream = null means SKIP
{
fileStreams.Add(null);
continue;
}
if (entry.IsFolder)
{
fileStreams.Add(null);
continue;
}
fileStreams.Add(outputStream);
}
this.archive.Extract(null, 0xFFFFFFFF, 0, new ArchiveStreamsCallback(fileStreams));
}
finally
{
if (!leave_open)
{
foreach (Stream stream in fileStreams)
{
if (stream != null)
{
stream.Dispose();
}
}
}
}
}
public IList<Entry> Entries
{
get
@ -264,13 +264,9 @@ namespace SevenZipExtractor
return result;
}
private static object _lockobj = new object();
private static string _staticLibraryFilePath;
private void InitializeAndValidateLibrary()
{
this.libraryFilePath = SetupLibrary();
SetupLibrary();
if (string.IsNullOrWhiteSpace(this.libraryFilePath))
{
string currentArchitecture = IntPtr.Size == 4 ? "x86" : "x64"; // magic check
@ -313,7 +309,10 @@ namespace SevenZipExtractor
}
}
private static string SetupLibrary()
private static string _staticLibraryFilePath = null;
private static object _lockobj = new object();
public static string SetupLibrary()
{
var zpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "7z-x64.dll");
if (_staticLibraryFilePath == null)

View File

@ -61,6 +61,9 @@
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="7zDll\" />
</ItemGroup>
<!--
<ItemGroup>
<Content Include="7z-x64.dll">

View File

@ -2,7 +2,7 @@
<package >
<metadata>
<id>SevenZipExtractor</id>
<version>1.0.12</version>
<version>1.0.13</version>
<title>SevenZipExtractor</title>
<authors>Eugene Sichkar, Alexander Selishchev, @matortheeternal, Hajin Jang, Artem Tarasov, Jose Pineiro, Raphael Stoeckli</authors>
<owners>Alexander Selishchev</owners>
@ -10,7 +10,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>C# wrapper for 7z.dll (included)</description>
<releaseNotes></releaseNotes>
<copyright>Copyright 2018</copyright>
<copyright>Copyright 2019</copyright>
<tags>7Zip APM Arj BZip2 Cab Chm Compound Cpio CramFS Deb Dll Dmg Exe Fat Flv GZip Hfs Iso Lzh Lzma Lzma86 Mach-O Mbr Mub Nsis Ntfs Ppmd Rar Rar5 Rpm Split SquashFS Swf Swfc Tar TE Udf UEFIc UEFIs Vhd Wim Xar XZ Z Zip</tags>
</metadata>
<files>

View File

@ -43,7 +43,7 @@
<ItemGroup Condition="'@(DllFiles)' != ''">
<None Include="@(DllFiles)">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

View File

@ -412,6 +412,7 @@ namespace SevenZipExtractor
public virtual void Seek(long offset, uint seekOrigin, IntPtr newPosition)
{
long Position = (uint) this.BaseStream.Seek(offset, (SeekOrigin) seekOrigin);
if (newPosition != IntPtr.Zero)
{
Marshal.WriteInt64(newPosition, Position);
@ -431,79 +432,6 @@ namespace SevenZipExtractor
}
}
// Can close base stream after period of inactivity and reopen it when needed.
// Useful for long opened archives (prevent locking archive file on disk).
internal class InStreamTimedWrapper : StreamWrapper, ISequentialInStream, IInStream
{
private string BaseStreamFileName;
private long BaseStreamLastPosition;
private Timer CloseTimer;
private const int KeepAliveInterval = 10 * 1000; // 10 sec
public InStreamTimedWrapper(Stream baseStream)
: base(baseStream)
{
if ((this.BaseStream is FileStream) && !this.BaseStream.CanWrite && this.BaseStream.CanSeek)
{
this.BaseStreamFileName = ((FileStream) this.BaseStream).Name;
this.CloseTimer = new Timer(new TimerCallback(this.CloseStream), null, KeepAliveInterval, Timeout.Infinite);
}
}
private void CloseStream(object state)
{
if (this.CloseTimer != null)
{
this.CloseTimer.Dispose();
this.CloseTimer = null;
}
if (this.BaseStream != null)
{
if (this.BaseStream.CanSeek)
{
this.BaseStreamLastPosition = this.BaseStream.Position;
}
this.BaseStream.Close();
this.BaseStream = null;
}
}
protected void ReopenStream()
{
if (this.BaseStream == null)
{
if (this.BaseStreamFileName != null)
{
this.BaseStream = new FileStream(this.BaseStreamFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
this.BaseStream.Position = this.BaseStreamLastPosition;
this.CloseTimer = new Timer(new TimerCallback(this.CloseStream), null, KeepAliveInterval, Timeout.Infinite);
}
else
{
throw new ObjectDisposedException("StreamWrapper");
}
}
else if (this.CloseTimer != null)
{
this.CloseTimer.Change(KeepAliveInterval, Timeout.Infinite);
}
}
public uint Read(byte[] data, uint size)
{
this.ReopenStream();
return (uint) this.BaseStream.Read(data, 0, (int) size);
}
public override void Seek(long offset, uint seekOrigin, IntPtr newPosition)
{
this.ReopenStream();
base.Seek(offset, seekOrigin, newPosition);
}
}
internal class OutStreamWrapper : StreamWrapper, ISequentialOutStream, IOutStream
{
public OutStreamWrapper(Stream baseStream) : base(baseStream)
@ -519,10 +447,12 @@ namespace SevenZipExtractor
public int Write(byte[] data, uint size, IntPtr processedSize)
{
this.BaseStream.Write(data, 0, (int) size);
if (processedSize != IntPtr.Zero)
{
Marshal.WriteInt32(processedSize, (int) size);
}
return 0;
}
}

View File

@ -268,5 +268,11 @@ namespace Wabbajack.Common
File.WriteAllText($"{DateTime.Now.ToString("yyyyMMddTHHmmss_crash_log.txt")}", ExceptionToString(e));
}
public static V GetOrDefault<K, V>(this IDictionary<K, V> dict, K key)
{
if (dict.TryGetValue(key, out V v)) return v;
return default(V);
}
}
}

View File

@ -31,6 +31,24 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="ICSharpCode.SharpZipLib, Version=1.1.0.145, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.1.1.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
@ -46,6 +64,7 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml.Linq" />
<Reference Include="Microsoft.CSharp" />
@ -58,6 +77,7 @@
<Compile Include="Consts.cs" />
<Compile Include="Data.cs" />
<Compile Include="DynamicIniData.cs" />
<Compile Include="FileExtractor.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utils.cs" />
<Compile Include="WorkQueue.cs" />

View File

@ -23,40 +23,73 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug (no commandargs)|Any CPU = Debug (no commandargs)|Any CPU
Debug (no commandargs)|x64 = Debug (no commandargs)|x64
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug (no commandargs)|x64.ActiveCfg = Debug|x64
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug (no commandargs)|x64.Build.0 = Debug|x64
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug|x64.ActiveCfg = Debug|x64
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug|x64.Build.0 = Debug|x64
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|Any CPU.Build.0 = Release|Any CPU
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|x64.ActiveCfg = Release|x64
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|x64.Build.0 = Release|x64
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug (no commandargs)|x64.ActiveCfg = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug (no commandargs)|x64.Build.0 = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug|x64.ActiveCfg = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug|x64.Build.0 = Debug|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Release|Any CPU.Build.0 = Release|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Release|x64.ActiveCfg = Release|Any CPU
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Release|x64.Build.0 = Release|Any CPU
{33602679-8484-40C7-A10C-774DFF5D8314}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug (no commandargs)|Any CPU
{33602679-8484-40C7-A10C-774DFF5D8314}.Debug (no commandargs)|Any CPU.Build.0 = Debug (no commandargs)|Any CPU
{33602679-8484-40C7-A10C-774DFF5D8314}.Debug (no commandargs)|x64.ActiveCfg = Debug (no commandargs)|x64
{33602679-8484-40C7-A10C-774DFF5D8314}.Debug (no commandargs)|x64.Build.0 = Debug (no commandargs)|x64
{33602679-8484-40C7-A10C-774DFF5D8314}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{33602679-8484-40C7-A10C-774DFF5D8314}.Debug|Any CPU.Build.0 = Debug|Any CPU
{33602679-8484-40C7-A10C-774DFF5D8314}.Debug|x64.ActiveCfg = Debug|x64
{33602679-8484-40C7-A10C-774DFF5D8314}.Debug|x64.Build.0 = Debug|x64
{33602679-8484-40C7-A10C-774DFF5D8314}.Release|Any CPU.ActiveCfg = Release|Any CPU
{33602679-8484-40C7-A10C-774DFF5D8314}.Release|Any CPU.Build.0 = Release|Any CPU
{33602679-8484-40C7-A10C-774DFF5D8314}.Release|x64.ActiveCfg = Release|x64
{33602679-8484-40C7-A10C-774DFF5D8314}.Release|x64.Build.0 = Release|x64
{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU
{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU
{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug (no commandargs)|x64.ActiveCfg = Debug|x64
{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug (no commandargs)|x64.Build.0 = Debug|x64
{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug|x64.ActiveCfg = Debug|x64
{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug|x64.Build.0 = Debug|x64
{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Release|Any CPU.Build.0 = Release|Any CPU
{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Release|x64.ActiveCfg = Release|x64
{FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Release|x64.Build.0 = Release|x64
{BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU
{BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU
{BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug (no commandargs)|x64.ActiveCfg = Debug|x64
{BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug (no commandargs)|x64.Build.0 = Debug|x64
{BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug|x64.ActiveCfg = Debug|x64
{BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug|x64.Build.0 = Debug|x64
{BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Release|Any CPU.Build.0 = Release|Any CPU
{BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Release|x64.ActiveCfg = Release|x64
{BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -13,5 +13,6 @@ namespace Wabbajack
/// </summary>
public partial class App : Application
{
}
}

View File

@ -1,4 +1,5 @@
using System;
using SevenZipExtractor;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
@ -50,6 +51,31 @@ namespace Wabbajack
}
}
private bool _ignoreMissingFiles = false;
public bool IgnoreMissingFiles
{
get
{
return _ignoreMissingFiles;
}
set
{
if (value)
{
if (MessageBox.Show("Setting this value could result in broken installations. \n Are you sure you want to continue?", "Ignore Missing Files?", MessageBoxButton.OKCancel, MessageBoxImage.Warning)
== MessageBoxResult.OK)
{
_ignoreMissingFiles = value;
}
}
else
{
_ignoreMissingFiles = value;
}
OnPropertyChanged("IgnoreMissingFiles");
}
}
private string _mo2Folder;
private string _modListName;
private ModList _modList;
@ -104,6 +130,7 @@ namespace Wabbajack
public AppState(Dispatcher d, String mode)
{
ArchiveFile.SetupLibrary();
LogFile = Assembly.GetExecutingAssembly().Location + ".log";
if (LogFile.FileExists())
@ -254,6 +281,7 @@ namespace Wabbajack
if (Mode == "Installing")
{
var installer = new Installer(_modList, Location, msg => this.LogMsg(msg));
installer.IgnoreMissingFiles = IgnoreMissingFiles;
var th = new Thread(() =>
{
try
@ -267,6 +295,8 @@ namespace Wabbajack
}
catch (Exception ex)
{
LogMsg(ex.StackTrace);
LogMsg(ex.InnerException.ToString());
LogMsg($"{ex.Message} - Can't continue");
}
});
@ -276,11 +306,21 @@ namespace Wabbajack
else
{
var compiler = new Compiler(_mo2Folder, msg => LogMsg(msg));
compiler.IgnoreMissingFiles = IgnoreMissingFiles;
compiler.MO2Profile = ModListName;
var th = new Thread(() =>
{
compiler.LoadArchives();
compiler.Compile();
try
{
compiler.LoadArchives();
compiler.Compile();
}
catch (Exception ex)
{
LogMsg(ex.StackTrace);
LogMsg(ex.InnerException.ToString());
LogMsg($"{ex.Message} - Can't continue");
}
});
th.Priority = ThreadPriority.BelowNormal;
th.Start();

View File

@ -1,6 +1,5 @@
using Compression.BSA;
using Newtonsoft.Json;
using SevenZipExtractor;
using SharpCompress.Archives;
using System;
using System.Collections.Concurrent;
@ -28,6 +27,8 @@ namespace Wabbajack
public dynamic MO2Ini { get; }
public string GamePath { get; }
public bool IgnoreMissingFiles { get; set; }
public string MO2DownloadsFolder
{
get
@ -120,36 +121,31 @@ namespace Wabbajack
return info;
}
using (var ar = new ArchiveFile(file))
Status("Indexing {0}", Path.GetFileName(file));
var streams = new Dictionary<string, (SHA256Managed, long)>();
FileExtractor.Extract(file, entry => {
var sha = new SHA256Managed();
var os = new CryptoStream(Stream.Null, sha, CryptoStreamMode.Write);
streams.Add(entry.Name, (sha, (long)entry.Size));
return os;
});
var indexed = new IndexedArchiveCache();
indexed.Hash = file.FileSHA256();
indexed.Entries = streams.Select(entry =>
{
Status("Indexing {0}", Path.GetFileName(file));
var streams = new Dictionary<string, (SHA256Managed, long)>();
ar.Extract(entry => {
if (entry.IsFolder) return null;
var sha = new SHA256Managed();
var os = new CryptoStream(Stream.Null, sha, CryptoStreamMode.Write);
streams.Add(entry.FileName, (sha, (long)entry.Size));
return os;
});
var indexed = new IndexedArchiveCache();
indexed.Hash = file.FileSHA256();
indexed.Entries = streams.Select(entry =>
return new IndexedEntry()
{
return new IndexedEntry()
{
Hash = entry.Value.Item1.Hash.ToBase64(),
Size = (long)entry.Value.Item2,
Path = entry.Key
};
}).ToList();
Hash = entry.Value.Item1.Hash.ToBase64(),
Size = (long)entry.Value.Item2,
Path = entry.Key
};
}).ToList();
streams.Do(e => e.Value.Item1.Dispose());
streams.Do(e => e.Value.Item1.Dispose());
indexed.ToJSON(metaname);
return LoadArchive(file);
}
indexed.ToJSON(metaname);
return LoadArchive(file);
}
public void Compile()
@ -184,8 +180,14 @@ namespace Wabbajack
Info(" {0}", file.To);
if (nomatch.Count() > 0)
{
Info("Exiting due to no way to compile these files");
return;
if (IgnoreMissingFiles)
{
Info("Continuing even though files were missing at the request of the user.");
}
else {
Info("Exiting due to no way to compile these files");
return;
}
}
InstallDirectives = results.Where(i => !(i is IgnoredDirectly)).ToList();
@ -256,17 +258,14 @@ namespace Wabbajack
var streams = new Dictionary<string, MemoryStream>();
Status($"Extracting {paths.Count} patch files from {archive.Name}");
// First we fetch the source files from the input archive
using (var a = new ArchiveFile(archive.AbsolutePath))
FileExtractor.Extract(archive.AbsolutePath, entry =>
{
a.Extract(entry =>
{
if (!paths.Contains(entry.FileName)) return null;
if (!paths.Contains(entry.Name)) return null;
var result = new MemoryStream();
streams.Add(entry.FileName, result);
return result;
}, false);
}
var result = new MemoryStream();
streams.Add(entry.Name, result);
return result;
}, false);
/*
using (var a = ArchiveFactory.Open(archive.AbsolutePath))
@ -286,6 +285,7 @@ namespace Wabbajack
var extracted = streams.ToDictionary(k => k.Key, v => v.Value.ToArray());
// Now Create the patches
Status("Building Patches for {0}", archive.Name);
Info("Building Patches for {0}", archive.Name);
group.PMap(entry =>
{
Info("Patching {0}", entry.To);

View File

@ -1,6 +1,5 @@
using CG.Web.MegaApiClient;
using Compression.BSA;
using SevenZipExtractor;
using System;
using System.Collections.Generic;
using System.IO;
@ -36,6 +35,7 @@ namespace Wabbajack
public Dictionary<string, string> HashedArchives { get; private set; }
public string NexusAPIKey { get; private set; }
public bool IgnoreMissingFiles { get; internal set; }
public void Info(string msg, params object[] args)
{
@ -79,7 +79,14 @@ namespace Wabbajack
{
foreach (var a in missing)
Info("Unable to download {0}", a.Name);
Error("Cannot continue, was unable to download one or more archives");
if (IgnoreMissingFiles)
{
Info("Missing some archives, but continuing anyways at the request of the user");
}
else
{
Error("Cannot continue, was unable to download one or more archives");
}
}
BuildFolderStructure();
InstallArchives();
@ -102,6 +109,7 @@ namespace Wabbajack
.Select(e => e.Substring(source_dir.Length + 1))
.ToList();
if(source_files.Count > 0)
using (var a = new BSABuilder())
{
@ -155,14 +163,17 @@ namespace Wabbajack
private void InstallArchives()
{
Info("Installing Archives");
Info("Grouping Install Files");
var grouped = ModList.Directives
.OfType<FromArchive>()
.GroupBy(e => e.ArchiveHash)
.ToDictionary(k => k.Key);
var archives = ModList.Archives
.Select(a => new { Archive = a, AbsolutePath = HashedArchives[a.Hash] })
.Select(a => new { Archive = a, AbsolutePath = HashedArchives.GetOrDefault(a.Hash) })
.Where(a => a.AbsolutePath != null)
.ToList();
Info("Installing Archives");
archives.PMap(a => InstallArchive(a.Archive, a.AbsolutePath, grouped[a.Archive.Hash]));
}
@ -173,20 +184,17 @@ namespace Wabbajack
var files = grouping.GroupBy(e => e.From)
.ToDictionary(e => e.Key);
using (var a = new ArchiveFile(absolutePath))
FileExtractor.Extract(absolutePath, entry =>
{
a.Extract(entry =>
if (files.TryGetValue(entry.Name, out var directives))
{
if (files.TryGetValue(entry.FileName, out var directives))
{
var directive = directives.First();
var absolute = Path.Combine(Outputfolder, directive.To);
if (absolute.FileExists()) File.Delete(absolute);
return File.OpenWrite(absolute);
}
return null;
});
}
var directive = directives.First();
var absolute = Path.Combine(Outputfolder, directive.To);
if (absolute.FileExists()) File.Delete(absolute);
return File.OpenWrite(absolute);
}
return null;
});
Status("Copying duplicated files for {0}", archive.Name);

View File

@ -16,6 +16,7 @@
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0, 16, 0, 16">
<TextBlock Text="{Binding Mode}" FontSize="16" FontWeight="Bold"></TextBlock>
@ -68,5 +69,6 @@
<ListBox local:AutoScrollBehavior.ScrollOnNewItem="True" Grid.Row ="5" ItemsSource="{Binding Log}">
</ListBox>
<Button Content="Begin" Grid.Row="6" Height="30" Command="{Binding Begin}"></Button>
<CheckBox Content="Ignore Missing Files" Grid.Row="7" Height="20" IsChecked="{Binding IgnoreMissingFiles}"></CheckBox>
</Grid>
</Window>

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Runtime.InteropServices;
@ -66,6 +67,7 @@ namespace Wabbajack
public static string GetNexusDownloadLink(NexusMod archive, string apikey)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var client = BaseNexusClient(apikey);
string url;
string get_url_link = String.Format("https://api.nexusmods.com/v1/games/{0}/mods/{1}/files/{2}/download_link.json",

View File

@ -66,6 +66,35 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug %28no commandargs%29|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug %28no commandargs%29\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Costura, Version=4.0.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
<HintPath>..\packages\Costura.Fody.4.0.0\lib\net40\Costura.dll</HintPath>

View File

@ -17,4 +17,7 @@
<FallbackCulture>en-US</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<StartArguments>"c:\Mod Organizer 2" "Nexus SSO Test" "c:\tmp\validate"</StartArguments>
</PropertyGroup>
</Project>