separated updater from main solution
This commit is contained in:
		
							
								
								
									
										21
									
								
								Oqtane.Updater/Oqtane.Updater.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								Oqtane.Updater/Oqtane.Updater.csproj
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|  | ||||
|   <PropertyGroup> | ||||
|     <TargetFramework>net5.0</TargetFramework> | ||||
|     <OutputType>Exe</OutputType> | ||||
|     <Version>2.1.0</Version> | ||||
|     <Product>Oqtane</Product> | ||||
|     <Authors>Shaun Walker</Authors> | ||||
|     <Company>.NET Foundation</Company> | ||||
|     <Description>Modular Application Framework for Blazor</Description> | ||||
|     <Copyright>.NET Foundation</Copyright> | ||||
|     <PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl> | ||||
|     <PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl> | ||||
|     <PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v2.1.0</PackageReleaseNotes> | ||||
|     <RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl> | ||||
|     <RepositoryType>Git</RepositoryType> | ||||
|     <RootNamespace>Oqtane</RootNamespace> | ||||
|     <IsPackable>false</IsPackable> | ||||
|   </PropertyGroup> | ||||
|  | ||||
| </Project> | ||||
							
								
								
									
										201
									
								
								Oqtane.Updater/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								Oqtane.Updater/Program.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,201 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.IO.Compression; | ||||
| using System.Threading; | ||||
|  | ||||
| namespace Oqtane.Updater | ||||
| { | ||||
|     class Program | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// This console application is responsible for extracting the contents of a previously downloaded Oqtane Upgrade package | ||||
|         /// </summary> | ||||
|         /// <param name="args"></param> | ||||
|         static void Main(string[] args) | ||||
|         { | ||||
|             // requires 2 arguments - the ContentRootPath and the WebRootPath of the site | ||||
|  | ||||
|             // for testing purposes set Oqtane.Upgrade as startup project and modify values below | ||||
|             //Array.Resize(ref args, 2); | ||||
|             //args[0] = @"C:\yourpath\oqtane.framework\Oqtane.Server"; | ||||
|             //args[1] = @"C:\yourpath\oqtane.framework\Oqtane.Server\wwwroot"; | ||||
|  | ||||
|             if (args.Length == 2) | ||||
|             { | ||||
|                 string contentrootfolder = args[0]; | ||||
|                 string webrootfolder = args[1]; | ||||
|                 string deployfolder = Path.Combine(contentrootfolder, "Packages"); | ||||
|                 string backupfolder = Path.Combine(contentrootfolder, "Backup"); | ||||
|  | ||||
|                 if (Directory.Exists(deployfolder)) | ||||
|                 { | ||||
|                     string packagename = ""; | ||||
|                     string[] packages = Directory.GetFiles(deployfolder, "Oqtane.Upgrade.*.zip"); | ||||
|                     if (packages.Length > 0) | ||||
|                     { | ||||
|                         packagename = packages[packages.Length - 1]; // use highest version  | ||||
|                     } | ||||
|  | ||||
|                     if (packagename != "") | ||||
|                     { | ||||
|                         // take the app offline | ||||
|                         if (File.Exists(Path.Combine(webrootfolder, "app_offline.bak"))) | ||||
|                         { | ||||
|                             File.Copy(Path.Combine(webrootfolder, "app_offline.bak"), Path.Combine(contentrootfolder, "app_offline.htm"), true); | ||||
|                         } | ||||
|  | ||||
|                         // get list of files in package with local paths | ||||
|                         List<string> files = new List<string>(); | ||||
|                         using (ZipArchive archive = ZipFile.OpenRead(packagename)) | ||||
|                         { | ||||
|                             foreach (ZipArchiveEntry entry in archive.Entries) | ||||
|                             { | ||||
|                                 files.Add(Path.Combine(contentrootfolder, entry.FullName)); | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         // ensure files are not locked | ||||
|                         if (CanAccessFiles(files)) | ||||
|                         { | ||||
|                             try | ||||
|                             { | ||||
|                                 //clear out backup folder | ||||
|                                 if (Directory.Exists(backupfolder)) | ||||
|                                 { | ||||
|                                     Directory.Delete(backupfolder, true); | ||||
|                                 } | ||||
|                                 Directory.CreateDirectory(backupfolder); | ||||
|  | ||||
|                                 // backup files | ||||
|                                 foreach (string file in files) | ||||
|                                 { | ||||
|                                     string filename = Path.Combine(backupfolder, file.Replace(contentrootfolder, "")); | ||||
|                                     if (!Directory.Exists(Path.GetDirectoryName(filename))) | ||||
|                                     { | ||||
|                                         Directory.CreateDirectory(Path.GetDirectoryName(filename)); | ||||
|                                     } | ||||
|                                     File.Copy(file, filename); | ||||
|                                 } | ||||
|  | ||||
|                                 // extract files | ||||
|                                 bool success = true; | ||||
|                                 try | ||||
|                                 { | ||||
|                                     using (ZipArchive archive = ZipFile.OpenRead(packagename)) | ||||
|                                     { | ||||
|                                         foreach (ZipArchiveEntry entry in archive.Entries) | ||||
|                                         { | ||||
|                                             string filename = Path.Combine(contentrootfolder, entry.FullName); | ||||
|                                             if (!Directory.Exists(Path.GetDirectoryName(filename))) | ||||
|                                             { | ||||
|                                                 Directory.CreateDirectory(Path.GetDirectoryName(filename)); | ||||
|                                             } | ||||
|                                             entry.ExtractToFile(filename, true); | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|                                 catch (Exception ex) | ||||
|                                 { | ||||
|                                     // an error occurred extracting a file | ||||
|                                     success = false; | ||||
|                                     Console.WriteLine("Update Not Successful: Error Extracting Files From Package - " + ex.Message); | ||||
|                                 } | ||||
|  | ||||
|                                 if (success) | ||||
|                                 { | ||||
|                                     // clean up backup | ||||
|                                     Directory.Delete(backupfolder, true); | ||||
|                                     // delete package | ||||
|                                     File.Delete(packagename); | ||||
|                                 } | ||||
|                                 else | ||||
|                                 { | ||||
|                                     // restore on failure | ||||
|                                     foreach (string file in files) | ||||
|                                     { | ||||
|                                         string filename = Path.Combine(backupfolder, file.Replace(contentrootfolder, "")); | ||||
|                                         File.Copy(filename, file); | ||||
|                                     } | ||||
|                                     // clean up backup | ||||
|                                     Directory.Delete(backupfolder, true); | ||||
|                                 } | ||||
|                             } | ||||
|                             catch (Exception ex) | ||||
|                             { | ||||
|                                 Console.WriteLine("Upgrade Not Successful: " + ex.Message); | ||||
|                             } | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             Console.WriteLine("Upgrade Not Successful: Some Files Are Locked"); | ||||
|                         } | ||||
|  | ||||
|                         // bring the app back online | ||||
|                         if (File.Exists(Path.Combine(contentrootfolder, "app_offline.htm"))) | ||||
|                         { | ||||
|                             File.Delete(Path.Combine(contentrootfolder, "app_offline.htm")); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         Console.WriteLine("Framework Upgrade Package Not Found"); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     Console.WriteLine("Framework Upgrade Folder " + deployfolder + " Does Not Exist"); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 Console.WriteLine("Missing ContentRootPath and WebRootPath Parameters"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private static bool CanAccessFiles(List<string> files) | ||||
|         { | ||||
|             // ensure files are not locked by another process - the shutdownTimeLimit defines the duration for app shutdown | ||||
|             bool canAccess = true; | ||||
|             FileStream stream = null; | ||||
|             int i = 0; | ||||
|             while (i < (files.Count - 1) && canAccess) | ||||
|             { | ||||
|                 string filepath = files[i]; | ||||
|                 int attempts = 0; | ||||
|                 bool locked = true; | ||||
|                 // try up to 30 times | ||||
|                 while (attempts < 30 && locked) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         if (File.Exists(filepath)) | ||||
|                         { | ||||
|                             stream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.None); | ||||
|                             locked = false; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             locked = false; | ||||
|                         } | ||||
|                     } | ||||
|                     catch // file is locked by another process | ||||
|                     { | ||||
|                         Thread.Sleep(1000); // wait 1 second | ||||
|                     } | ||||
|                     finally | ||||
|                     { | ||||
|                         stream?.Close(); | ||||
|                     } | ||||
|                     attempts += 1; | ||||
|                 } | ||||
|                 if (locked) | ||||
|                 { | ||||
|                     canAccess = false; | ||||
|                 } | ||||
|                 i += 1; | ||||
|             } | ||||
|             return canAccess; | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Shaun Walker
					Shaun Walker