diff --git a/src/Files.App/App.xaml.cs b/src/Files.App/App.xaml.cs index ce8f7b3798de..f9202c20997b 100644 --- a/src/Files.App/App.xaml.cs +++ b/src/Files.App/App.xaml.cs @@ -226,6 +226,7 @@ await Task.WhenAll( var updateService = Ioc.Default.GetRequiredService(); await updateService.CheckForUpdates(); await updateService.DownloadMandatoryUpdates(); + await updateService.CheckAndUpdateFilesLauncherAsync(); await updateService.CheckLatestReleaseNotesAsync(); static async Task OptionalTask(Task task, bool condition) diff --git a/src/Files.App/Assets/FilesOpenDialog/FilesLauncher.exe b/src/Files.App/Assets/FilesOpenDialog/FilesLauncher.exe index 4f47b29ea154..3f2779c07963 100644 Binary files a/src/Files.App/Assets/FilesOpenDialog/FilesLauncher.exe and b/src/Files.App/Assets/FilesOpenDialog/FilesLauncher.exe differ diff --git a/src/Files.App/Assets/FilesOpenDialog/FilesLauncher.exe.sha256 b/src/Files.App/Assets/FilesOpenDialog/FilesLauncher.exe.sha256 new file mode 100644 index 000000000000..55822f24124e --- /dev/null +++ b/src/Files.App/Assets/FilesOpenDialog/FilesLauncher.exe.sha256 @@ -0,0 +1 @@ +126534c53b4865d8b71d9378ce8d7071ff6dd71a58a0773345867dcfb80952a7 diff --git a/src/Files.App/ServicesImplementation/SideloadUpdateService.cs b/src/Files.App/ServicesImplementation/SideloadUpdateService.cs index 5d3b55d154ee..2305205b62fd 100644 --- a/src/Files.App/ServicesImplementation/SideloadUpdateService.cs +++ b/src/Files.App/ServicesImplementation/SideloadUpdateService.cs @@ -153,6 +153,49 @@ public async Task CheckForUpdates() } } + public async Task CheckAndUpdateFilesLauncherAsync() + { + var destFolderPath = Path.Combine(UserDataPaths.GetDefault().LocalAppData, "Files"); + var destExeFilePath = Path.Combine(destFolderPath, "FilesLauncher.exe"); + + if (Path.Exists(destExeFilePath)) + { + var hashEqual = false; + var srcHashFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/FilesOpenDialog/FilesLauncher.exe.sha256")); + var destHashFilePath = Path.Combine(destFolderPath, "FilesLauncher.exe.sha256"); + + if (Path.Exists(destHashFilePath)) + { + using var srcStream = (await srcHashFile.OpenReadAsync()).AsStream(); + using var destStream = File.OpenRead(destHashFilePath); + + hashEqual = HashEqual(srcStream, destStream); + } + + if (!hashEqual) + { + var srcExeFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/FilesOpenDialog/FilesLauncher.exe")); + var destFolder = await StorageFolder.GetFolderFromPathAsync(destFolderPath); + + await srcExeFile.CopyAsync(destFolder, "FilesLauncher.exe", NameCollisionOption.ReplaceExisting); + await srcHashFile.CopyAsync(destFolder, "FilesLauncher.exe.sha256", NameCollisionOption.ReplaceExisting); + + App.Logger.Info("FilesLauncher updated."); + } + } + + bool HashEqual(Stream a, Stream b) + { + Span bufferA = stackalloc byte[64]; + Span bufferB = stackalloc byte[64]; + + a.Read(bufferA); + b.Read(bufferB); + + return bufferA.SequenceEqual(bufferB); + } + } + private async Task StartBackgroundDownload() { try diff --git a/src/Files.App/ServicesImplementation/UpdateService.cs b/src/Files.App/ServicesImplementation/UpdateService.cs index 88f7b4823e93..228a470a28d1 100644 --- a/src/Files.App/ServicesImplementation/UpdateService.cs +++ b/src/Files.App/ServicesImplementation/UpdateService.cs @@ -11,6 +11,7 @@ using System.Threading; using System.Threading.Tasks; using Windows.Services.Store; +using Windows.Storage; using WinRT.Interop; namespace Files.App.ServicesImplementation @@ -178,6 +179,49 @@ public async Task CheckLatestReleaseNotesAsync(CancellationToken cancellationTok } } + public async Task CheckAndUpdateFilesLauncherAsync() + { + var destFolderPath = Path.Combine(UserDataPaths.GetDefault().LocalAppData, "Files"); + var destExeFilePath = Path.Combine(destFolderPath, "FilesLauncher.exe"); + + if (Path.Exists(destExeFilePath)) + { + var hashEqual = false; + var srcHashFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/FilesOpenDialog/FilesLauncher.exe.sha256")); + var destHashFilePath = Path.Combine(destFolderPath, "FilesLauncher.exe.sha256"); + + if (Path.Exists(destHashFilePath)) + { + using var srcStream = (await srcHashFile.OpenReadAsync()).AsStream(); + using var destStream = File.OpenRead(destHashFilePath); + + hashEqual = HashEqual(srcStream, destStream); + } + + if (!hashEqual) + { + var srcExeFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/FilesOpenDialog/FilesLauncher.exe")); + var destFolder = await StorageFolder.GetFolderFromPathAsync(destFolderPath); + + await srcExeFile.CopyAsync(destFolder, "FilesLauncher.exe", NameCollisionOption.ReplaceExisting); + await srcHashFile.CopyAsync(destFolder, "FilesLauncher.exe.sha256", NameCollisionOption.ReplaceExisting); + + App.Logger.Info("FilesLauncher updated."); + } + } + + bool HashEqual(Stream a, Stream b) + { + Span bufferA = stackalloc byte[64]; + Span bufferB = stackalloc byte[64]; + + a.Read(bufferA); + b.Read(bufferB); + + return bufferA.SequenceEqual(bufferB); + } + } + // WINUI3 private static ContentDialog SetContentDialogRoot(ContentDialog contentDialog) { diff --git a/src/Files.Backend/Services/IUpdateService.cs b/src/Files.Backend/Services/IUpdateService.cs index 9134da609831..ffe3ee708767 100644 --- a/src/Files.Backend/Services/IUpdateService.cs +++ b/src/Files.Backend/Services/IUpdateService.cs @@ -38,5 +38,10 @@ public interface IUpdateService : INotifyPropertyChanged /// Gets release notes for the latest release /// Task GetLatestReleaseNotesAsync(CancellationToken cancellationToken = default); + + /// + /// Replace FilesLauncher.exe if it is used and has been updated + /// + Task CheckAndUpdateFilesLauncherAsync(); } } diff --git a/src/Files.OpenDialog/FilesLauncher/FilesLauncher.vcxproj b/src/Files.OpenDialog/FilesLauncher/FilesLauncher.vcxproj index 042934654daf..8f6a74b9b772 100644 --- a/src/Files.OpenDialog/FilesLauncher/FilesLauncher.vcxproj +++ b/src/Files.OpenDialog/FilesLauncher/FilesLauncher.vcxproj @@ -189,7 +189,8 @@ $(OutDir)FilesLauncher$(TargetExt) - xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" + xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" +certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil">"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256" @@ -211,7 +212,8 @@ $(OutDir)FilesLauncher$(TargetExt) - xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" + xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" +certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil">"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256" @@ -233,7 +235,8 @@ $(OutDir)FilesLauncher$(TargetExt) - xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" + xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" +certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil">"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256" @@ -251,7 +254,8 @@ $(OutDir)FilesLauncher$(TargetExt) - xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" + xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" +certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil">"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256" @@ -269,7 +273,8 @@ $(OutDir)FilesLauncher$(TargetExt) - xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" + xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" +certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil">"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256" @@ -291,7 +296,8 @@ $(OutDir)FilesLauncher$(TargetExt) - xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" + xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" +certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil">"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256" @@ -313,7 +319,8 @@ $(OutDir)FilesLauncher$(TargetExt) - xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" + xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" +certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil">"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256" @@ -335,7 +342,8 @@ $(OutDir)FilesLauncher$(TargetExt) - xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" + xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" +certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil">"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256" @@ -357,7 +365,8 @@ $(OutDir)FilesLauncher$(TargetExt) - xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" + xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog" +certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil">"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256"