Project: LinqPad.Auto.Updater



Run LINQPad as administrator.

Auto update LINQPad from the official website using CodeDom to dynamically generate the application to overwrite the old files:
void Main()
{
	var linqPad = new LinqPad(Assembly.GetCallingAssembly());
	
	if (!linqPad.NeedUpdate())
	{
		"LINQPad is uptodate.".Dump();
		return;
	}
	
	string
		.Format(
			"LINQPad is not updated.{0}{0}Current {1}. New {2}.",
			Environment.NewLine,
			linqPad.CurrentVersion,
			linqPad.LatestVersion)
			.Dump();
			
	if (!IsRunningAsAdmin())
	{
		"\r\nTo LINQPad run it as administrator.".Dump();
		return;
	}
	
	Console.WriteLine(
		"This script will close LINQPad to update it.{0}Press 1 to continue, 2 to exit.", Environment.NewLine);
	var choise = int.Parse(Console.ReadLine());
	
	if (choise == 2)
	{
		return;
	}
	
	var extractPath = DownloadLinqPadAndExtract(linqPad.LatestVersion).Dump();
	
	var linqPadFolder = new DirectoryInfo(".").FullName.Dump();
	
	UpdateLinqPad(linqPadFolder, extractPath);	
}

private static void UpdateLinqPad(string linqPadFolder, string extractPath)
{
	var updaterPath =
		Path.Combine(Path.GetTempPath(), "LinqPad.Update.exe");
	
	File.Delete(updaterPath);

	var codeDomProvider = CodeDomProvider.CreateProvider("CSharp", new Dictionary<string, string>{ { "CompilerVersion", "v4.0" }});

	var compilerParameters = 
		new CompilerParameters
			{
				GenerateExecutable = true,
				OutputAssembly = updaterPath
			};
			
	compilerParameters.ReferencedAssemblies.Add("System.dll");
	compilerParameters.ReferencedAssemblies.Add("System.Core.dll");

	var updaterCode =
		"namespace EyeOpen.LINQPadUpdater.Shell" + Environment.NewLine +
		"{" + Environment.NewLine +
		"	using System;" + Environment.NewLine +
		"	using System.Diagnostics;" + Environment.NewLine +
		"	using System.IO;" + Environment.NewLine +
		"	using System.Linq;" + Environment.NewLine +
		string.Empty + Environment.NewLine +
		string.Empty + Environment.NewLine +
		"	internal static class Program" + Environment.NewLine +
		"	{" + Environment.NewLine +
		"		public static void Main(string[] args)" + Environment.NewLine +
		"		{" + Environment.NewLine +
		"			var linqPadFolder = args[0];" + Environment.NewLine +
		"			var extractPath = args[1];" + Environment.NewLine +
		string.Empty + 
		"			Process" + Environment.NewLine +
		"				.GetProcessesByName(\"LINQPad\")" + Environment.NewLine +
		"				.ToList()" + Environment.NewLine +
		"				.ForEach(process => { if (!process.CloseMainWindow()) process.Kill(); process.WaitForExit(); } );" + Environment.NewLine +
		string.Empty + 
		"			Directory" + Environment.NewLine +
		"				.GetFiles(extractPath)" + Environment.NewLine +
		"				.ToList()" + Environment.NewLine +
		"				.ForEach(file => File.Copy(file, Path.Combine(linqPadFolder, new FileInfo(file).Name), true));" + Environment.NewLine +
		string.Empty + Environment.NewLine +
		"			Process.Start(Path.Combine(linqPadFolder, \"LINQPad.exe\"));" + Environment.NewLine +
		"		}" + Environment.NewLine +
		"	}" + Environment.NewLine +
		"}";
		
		var results = 
			codeDomProvider.CompileAssemblyFromSource(compilerParameters, updaterCode);
		
		if (results.Errors.Count > 0)
		{
			results.Output.Dump();
			return;
		}
		
		using (Process.Start(results.PathToAssembly, string.Format("\"{0}\" \"{1}\"", linqPadFolder, extractPath)))
		{
		}
}

private static string DownloadLinqPadAndExtract(Version latestVersion)
{
	var tempPath = Path.GetTempPath();
	
	var filePath =
		Path.Combine(tempPath, string.Format("LINQPad.v{0}.zip", latestVersion));

	var extractPath = Path.Combine(tempPath, "LINQPad");

	if (!File.Exists(filePath))
	{
		DownloadLinqPad(filePath);		
	}
	
	UnzipFile(filePath, extractPath);
	
	return extractPath;
}

private static void DownloadLinqPad(string filePath)
{
	"Downloading LINQPad...".Dump();
	
	var linqpad = "http://www.linqpad.net/GetFile.aspx?preview+LINQPad4.zip";

	new WebClient()
		.DownloadFile(linqpad, filePath);		
}

private static void UnzipFile(string zipPath, string extractPath)
{
	var shellType = Type.GetTypeFromProgID("Shell.Application");
	
	dynamic shell = 
		Activator.CreateInstance(shellType);
		
	dynamic scrFolder = shell.Namespace(zipPath);       
	dynamic destFolder = shell.NameSpace(extractPath);
	dynamic items = scrFolder.Items();
	destFolder.CopyHere(items, 20);
}

private bool IsRunningAsAdmin()
{
	bool isAdmin = false;
	var currentIdentity = WindowsIdentity.GetCurrent();
	if (currentIdentity != null)
	{
		WindowsPrincipal pricipal = new WindowsPrincipal(currentIdentity);
		isAdmin = pricipal.IsInRole(WindowsBuiltInRole.Administrator);
		pricipal = null;
	}
	return isAdmin;
}

public class LinqPad
{
	public LinqPad(Assembly callingAssembly)
	{
		LatestVersion = GetLatestBetaVersion();		
		CurrentVersion = GetCurrentVersion(callingAssembly);
	}

	public Version CurrentVersion { get; private set; }

	public Version LatestVersion { get; private set; }

	public bool NeedUpdate()
	{		
		return CurrentVersion < LatestVersion;
	}
	
	private Version GetLatestBetaVersion()
	{
		using (var client = new WebClient())
		{
			var versionText = 
				client.DownloadString("http://www.linqpad.net/updates40/betaversionx.txt");
			
			return		
				new Version(versionText.Substring(0, 1) + "." + versionText.Substring(1) + ".0");
		}
	}
	
	private Version GetCurrentVersion(Assembly callingAssembly)
	{
		var assemblyFileVersionAttributeList = callingAssembly.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), true);
		var assemblyFileVersionAttribute = assemblyFileVersionAttributeList.OfType<AssemblyFileVersionAttribute>().Single<AssemblyFileVersionAttribute>();
	
		return
			new Version(assemblyFileVersionAttribute.Version);
	}
}

Last edited Apr 12, 2012 at 6:07 PM by teoarch, version 2

Comments

No comments yet.