using System; using System.Drawing; using System.Collections; using System.Resources; using System.Windows.Forms; using System.IO; using System.Xml; using System.Globalization; namespace resxtract { /// /// A command line utility to extract binary resources from xml resource (resx) files and /// write them to separate correctly named files. /// /// An attempt is made to reconstruct an object according to the Type definition /// in the xml. Some types (Bitmap, Icon) are constructed from the underlying byte array /// and written using their formal methods. Some resources (WAV files for example) are encoded /// as plain byte arrays, so they are written directly to a file. /// Note from Greg - I'm not really sure that this code represents the easiest way of /// extracting the binary resources. I searched through the System.Resources namespace looking /// for some standard utility classes to help me produce short and elegant code, but I couldn't /// find any. So I'm stuck with the logic described above to inspect the Types, which I'm /// not really happy with, as it doesn't seem very general purpose. Any advice on this matter /// would be most welcome. /// class AppMain { //========================================================================================== [STAThread] static int Main(string[] args) { AppMain app = new AppMain(); try { return app.Run(args); } catch (Exception ex) { Console.WriteLine("Failed to process '{0}' - {1}",args[0],ex.Message); return 4; } } //========================================================================================== public AppMain() { } //========================================================================================== public int Run(string[] args) { if ((args.Length == 0) || ((args.Length == 1) && (args[0] == "/?"))) { ShowHelp(); return 1; } if (!File.Exists(args[0])) { Console.WriteLine("Resource file '{0}' does not exist",args[0]); return 2; } string outFolder = null; if (args.Length >= 2) { if (!Directory.Exists(args[1])) { Console.WriteLine("Output folder '{0}' does not exist",args[1]); return 3; } outFolder = args[1]; } XmlDocument xdoc = new XmlDocument(); xdoc.Load(args[0]); XmlNodeList nl = xdoc.GetElementsByTagName("data"); foreach (XmlNode n in nl) { string name = SafeSafeAttr(n,"name"); string type = SafeSafeAttr(n,"type"); string mime = SafeSafeAttr(n,"mimetype"); string val = n["value"].InnerText; if (type != null) { Type t = Type.GetType(type); //----------------------------------------------------------------- if (t == typeof(Bitmap)) { string ext = Path.GetExtension(name).ToLower(CultureInfo.InvariantCulture); byte[] buffer = Convert.FromBase64String(val); MemoryStream ms = new MemoryStream(buffer); Bitmap img = new Bitmap(ms); switch (ext) { case ".bmp" : img.Save(MakeFileName(outFolder,name),System.Drawing.Imaging.ImageFormat.Bmp); break; case ".gif" : img.Save(MakeFileName(outFolder,name),System.Drawing.Imaging.ImageFormat.Gif); break; case ".jpg" : case ".jpeg" : img.Save(MakeFileName(outFolder,name),System.Drawing.Imaging.ImageFormat.Jpeg); break; default : img.Save(MakeFileName(outFolder,name),System.Drawing.Imaging.ImageFormat.Bmp); break; } ms.Close(); img.Dispose(); Console.WriteLine("Extracted Bitmap '{0}' ({1} bytes)",name,buffer.Length); } //----------------------------------------------------------------- if (t == typeof(Icon)) { byte[] buffer = Convert.FromBase64String(val); MemoryStream ms = new MemoryStream(buffer); Icon ico = new Icon(ms); FileStream fs = new FileStream(MakeFileName(outFolder,name),FileMode.Create,FileAccess.Write); ico.Save(fs); fs.Close(); Console.WriteLine("Extracted Icon '{0}' ({1} bytes)",name,buffer.Length); ico.Dispose(); } //----------------------------------------------------------------- if (t.IsArray && (t.GetElementType() == typeof(byte))) { byte[] buffer = Convert.FromBase64String(val); BinaryWriter bf = new BinaryWriter(new FileStream(MakeFileName(outFolder,name),FileMode.Create,FileAccess.Write)); bf.Write(buffer); bf.Close(); Console.WriteLine("Extracted Buffer '{0}' ({1} bytes)",name,buffer.Length); } } } return 0; } //========================================================================================== private string MakeFileName(string folder, string fileName) { if ((folder == null) || (folder.Length == 0)) return fileName; return Path.Combine(folder,fileName); } //========================================================================================== private string SafeSafeAttr(XmlNode n, string attrName) { XmlAttribute attr = n.Attributes[attrName]; if (attr == null) return null; return attr.Value; } //========================================================================================== private void ShowHelp() { string[] lines = { "DESCRIPTION", " Extracts binary objects from xml resource (resx) files.", "SYNTAX\n" + " resxtract resxfile [ outfolder ]", "PARAMETERS", " resxfile ....... The resx file to process.", " outfolder ...... The optional output folder, default is the current folder." }; for (int i=0; i