Created
April 29, 2022 09:43
-
-
Save stephenbradshaw/25fce028729d22b0f997cd3007a39748 to your computer and use it in GitHub Desktop.
C# code for extracting resources from .Net assemblies to auto named files in pwd on disk - handles costura compressed files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.IO; | |
using System.IO.Compression; | |
using System.Linq; | |
using System.Reflection; | |
using System.Text; | |
using System; | |
// Compile with: csc extractor.cs | |
// Has extremely minimal error handling and testing and takes most of its code from StackOverflow ;) | |
namespace Extractor | |
{ | |
class Extractor { | |
private static byte[] ReadFully(Stream input) | |
{ | |
using (MemoryStream ms = new MemoryStream()) | |
{ | |
input.CopyTo(ms); | |
return ms.ToArray(); | |
} | |
} | |
private static byte[] Decompress(byte[] data) | |
{ | |
byte[] decompressedArray = null; | |
try | |
{ | |
using (MemoryStream decompressedStream = new MemoryStream()) | |
{ | |
using (MemoryStream compressStream = new MemoryStream(data)) | |
{ | |
using (DeflateStream deflateStream = new DeflateStream(compressStream, CompressionMode.Decompress)) | |
{ | |
deflateStream.CopyTo(decompressedStream); | |
} | |
} | |
decompressedArray = decompressedStream.ToArray(); | |
} | |
} | |
catch (Exception exception) | |
{ | |
Console.WriteLine(exception.ToString()); | |
} | |
return decompressedArray; | |
} | |
private static void SaveDecompressedFileStream(String path, Stream stream) | |
{ | |
byte[] decompressed = Decompress(ReadFully(stream)); | |
File.WriteAllBytes(path, decompressed); | |
} | |
private static void SaveFileStream(String path, Stream stream) | |
{ | |
byte[] decompressed = ReadFully(stream); | |
File.WriteAllBytes(path, decompressed); | |
} | |
static void Main(string[] args) | |
{ | |
if (args.Length != 1) { | |
Console.WriteLine("Provide filename as parameter 1"); | |
} | |
else { | |
if (File.Exists(args[0])) | |
{ | |
Console.WriteLine("Extracting resources from {0}", args[0]); | |
Assembly assembly = Assembly.LoadFrom(args[0]); | |
// Create a lookup table from the Assembly References for more friendly output filenames for some costura resources | |
IDictionary<string, string> lowercaseLookup = new Dictionary<string, string>(); | |
foreach (var refassembly in assembly.GetReferencedAssemblies()) { | |
lowercaseLookup.Add(refassembly.Name.ToLower(), refassembly.Name); | |
} | |
foreach (var resourcename in assembly.GetManifestResourceNames()) | |
{ | |
bool compressed = false; | |
StringBuilder fn = new(); | |
string[] bits = resourcename.Split("."); | |
if (bits.Length > 3) { | |
if ( (bits[0].Equals("costura")) && (bits[bits.Length-1].Equals("compressed")) ) | |
{ | |
if (lowercaseLookup.ContainsKey(bits[1])) | |
{ | |
bits[1] = lowercaseLookup[bits[1]]; | |
} | |
string[] nb = bits.Skip(1).Take(bits.Length - 2).ToArray(); | |
fn.Append(String.Join(".", nb)); | |
compressed = true; | |
} | |
else{ | |
fn.Append(resourcename); | |
} | |
} | |
else | |
{ | |
fn.Append(resourcename); | |
} | |
Stream stream = assembly.GetManifestResourceStream(resourcename); | |
if (compressed) { | |
Console.WriteLine("Extracting compressed resource {0} into file {1}", resourcename, fn); | |
SaveDecompressedFileStream(fn.ToString(), stream); | |
} | |
else | |
{ | |
Console.WriteLine("Extracting resource {0} into file {1}", resourcename, fn); | |
SaveFileStream(fn.ToString(), stream); | |
} | |
} | |
} | |
else{ | |
Console.WriteLine("File {0} does not exist!", args[0]); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment