Click here to Skip to main content
15,892,537 members
Articles / Programming Languages / C#

Reducing the Size of .NET Applications

Rate me:
Please Sign up or sign in to vote.
3.74/5 (22 votes)
3 Oct 20048 min read 168.6K   278   54  
An article on reducing size of .NET executables.
using System;
using System.IO;
using System.Collections;
using System.Resources;
using System.Text;

namespace netz
{
	public class Netz
	{
		#region vars
		
		private static ResMan rm = null;
		private static GenData genData = null;
		private static bool singleExe = false;
		private static bool exeFileSet = false; // a single exe must be given
		private static readonly string LOGPREFIX = "     ";
				
		#endregion vars

		[STAThread]
		static void Main(string[] args)
		{
			Help.PrintLogo();
			bool printStackStrace = false;
			ArrayList files = new ArrayList();
			try
			{
				genData = new GenData();
				if(args.Length <= 0) throw new Exception("arguments required");
				for(int i = 0; i < args.Length; i++)
				{
					if((args[i][0] == '-') || (args[i][0] == '/'))
					{
						string arg = args[i].Substring(1, args[i].Length - 1).ToLower();
						switch(arg)
						{
							case "v":
								printStackStrace = true;
								break;
							case "?":
								Help.ShowHelp();
								return;
							case "s":
								singleExe = true;
								break;
							case "c":
								genData.console = true;
								break;
							case "i":
								genData.iconFile = args[++i];
								break;
							case "b":
								genData.batchMode = true;
								break;
							case "p":
								genData.privatePath = args[++i];
								break;
							default:
								throw new Exception("unknown argument: " + args[i]);
						}
					}
					else
					{
						if(!File.Exists(args[i]))
							throw new Exception("file not found: " + args[i]);
						if(args[i].ToLower().EndsWith(".exe"))
						{
							if(exeFileSet)
								throw new Exception("a single EXE must be specified");
							exeFileSet = true;
							OutDirMan.OutDir = args[i] + ".netz";
						}
						files.Add(args[i]);
					}
				}
				if(singleExe && (!exeFileSet))
					throw new Exception("an EXE file must be specified for the -s option");
				Proceed(files);
			}
			catch(Exception ex)
			{
				Logger.LogErr(ex.Message + 
					(printStackStrace ? "\r\n" + ex.StackTrace : string.Empty));
				Logger.Log("\r\nType -? for help!");
			}
		}

		private static void Proceed(ArrayList files)
		{
			if(files.Count <= 0) throw new Exception("no files");
			long start = DateTime.Now.Ticks;
			OutDirMan.Make();
			Logger.Log("Processing:       " + files.Count + " file(s)\r\n");
			ProcessFiles(files);
			if(exeFileSet)
			{
				MakeStarterApp();
			}
			start = DateTime.Now.Ticks - start;
			Logger.Log("\r\n *|  Done [" + ElapsedTime(start) + "]");
		}

		private static string ElapsedTime(long delta)
		{
			TimeSpan ts = new TimeSpan(delta);
			StringBuilder sb = new StringBuilder();
			sb.Append(ts.Hours.ToString("00")).Append(":");
			sb.Append(ts.Minutes.ToString("00")).Append(":");
			sb.Append(ts.Seconds.ToString("00")).Append(".");
			sb.Append(ts.Milliseconds);
			return sb.ToString();
		}

		private static void ProcessFiles(ArrayList files)
		{
			rm = new ResMan();
			for(int i = 0; i < files.Count; ++i)
			{
				string file = (string)files[i];
				try
				{
					ProcessFile(i + 1, file);
				}
				catch(Exception ex)
				{
					Logger.LogErr(ex.Message + " " + file);
				}
			}
			rm.Save();
		}

		private static long lastLength = 0L;
		private static void ProcessFile(int i, string file)
		{
			FileInfo fi = new FileInfo(file);
			lastLength = fi.Length;
			Logger.Log((i < 10 ? " " : string.Empty) + i.ToString()
				+ "|  " + file + " "
				+ Utils.FormatFileSize(fi.Length));
			fi = null;
			if(file.ToLower().EndsWith(".exe"))
				ProcessExeFile(file);
			else if(file.ToLower().EndsWith(".dll"))
				ProcessDllFile(file);
			else throw new Exception("unsupported file type suffix");
		}

		internal static void LogZipSize(long zipLength)
		{
			if(lastLength <= 0L) return;
			Logger.Log(LOGPREFIX + "-> "
				+ Utils.FormatFileSize(zipLength)
				+ " - "
				+ (100L - ((zipLength * 100L) / lastLength)).ToString("00")
				+ "%");
		}

		private static void ProcessExeFile(string file)
		{
			string zipFile = Zipper.ZipFile(file);
			rm.AddResource("app.exe", Utils.ReadFile(zipFile));
			File.Delete(zipFile);

			genData.exeFileName = Path.GetFileName(file);
			genData.assemblyInfo = starter.AssemblyInfoGen.MakeAssemblyInfo(file);
			ProcessExeIcon(file);
		}

		private static void ProcessExeIcon(string file)
		{
			if(genData.iconFile != null)
			{ 
				if(genData.batchMode)
				{
					try
					{
						string ico = OutDirMan.MakeOutFileName(Path.GetFileName(genData.iconFile));
						if(!File.Exists(ico))
							File.Copy(genData.iconFile, ico);
					}
					catch{}
				}
				return;
			}
			try
			{
				genData.iconFile = OutDirMan.MakeOutFileName("App.ico");
				starter.IconExtractor.SaveExeIcon(file, genData.iconFile);
			}
			catch(Exception ex)
			{
				genData.iconFile = null;
				Logger.Log(LOGPREFIX + "Warning: ICON " + ex.Message);
			}
		}

		private static void ProcessDllFile(string file)
		{
			string zipFile = Zipper.ZipFile(file);
			if(singleExe)
			{ 
				rm.AddResource(Path.GetFileNameWithoutExtension(file), Utils.ReadFile(zipFile));
				File.Delete(zipFile);
			}
		}

		private static void MakeStarterApp()
		{
			starter.StarterGen sg = new starter.StarterGen(genData);
			sg.Make(rm.ResourceFilePath);
			if(!genData.batchMode) File.Delete(rm.ResourceFilePath);
			try
			{
				File.Copy("zip.dll", OutDirMan.MakeOutFileName("zip.dll"), false);
			}
			catch{}
		}

	}//EOC
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions