Skip to content

Commit fa2664a

Browse files
authored
Feature: Auto update feature of FilesLauncher (#11750)
1 parent 0f3fc5b commit fa2664a

File tree

7 files changed

+112
-9
lines changed

7 files changed

+112
-9
lines changed

src/Files.App/App.xaml.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ await Task.WhenAll(
226226
var updateService = Ioc.Default.GetRequiredService<IUpdateService>();
227227
await updateService.CheckForUpdates();
228228
await updateService.DownloadMandatoryUpdates();
229+
await updateService.CheckAndUpdateFilesLauncherAsync();
229230
await updateService.CheckLatestReleaseNotesAsync();
230231

231232
static async Task OptionalTask(Task task, bool condition)
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
126534c53b4865d8b71d9378ce8d7071ff6dd71a58a0773345867dcfb80952a7

src/Files.App/ServicesImplementation/SideloadUpdateService.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,49 @@ public async Task CheckForUpdates()
153153
}
154154
}
155155

156+
public async Task CheckAndUpdateFilesLauncherAsync()
157+
{
158+
var destFolderPath = Path.Combine(UserDataPaths.GetDefault().LocalAppData, "Files");
159+
var destExeFilePath = Path.Combine(destFolderPath, "FilesLauncher.exe");
160+
161+
if (Path.Exists(destExeFilePath))
162+
{
163+
var hashEqual = false;
164+
var srcHashFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/FilesOpenDialog/FilesLauncher.exe.sha256"));
165+
var destHashFilePath = Path.Combine(destFolderPath, "FilesLauncher.exe.sha256");
166+
167+
if (Path.Exists(destHashFilePath))
168+
{
169+
using var srcStream = (await srcHashFile.OpenReadAsync()).AsStream();
170+
using var destStream = File.OpenRead(destHashFilePath);
171+
172+
hashEqual = HashEqual(srcStream, destStream);
173+
}
174+
175+
if (!hashEqual)
176+
{
177+
var srcExeFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/FilesOpenDialog/FilesLauncher.exe"));
178+
var destFolder = await StorageFolder.GetFolderFromPathAsync(destFolderPath);
179+
180+
await srcExeFile.CopyAsync(destFolder, "FilesLauncher.exe", NameCollisionOption.ReplaceExisting);
181+
await srcHashFile.CopyAsync(destFolder, "FilesLauncher.exe.sha256", NameCollisionOption.ReplaceExisting);
182+
183+
App.Logger.Info("FilesLauncher updated.");
184+
}
185+
}
186+
187+
bool HashEqual(Stream a, Stream b)
188+
{
189+
Span<byte> bufferA = stackalloc byte[64];
190+
Span<byte> bufferB = stackalloc byte[64];
191+
192+
a.Read(bufferA);
193+
b.Read(bufferB);
194+
195+
return bufferA.SequenceEqual(bufferB);
196+
}
197+
}
198+
156199
private async Task StartBackgroundDownload()
157200
{
158201
try

src/Files.App/ServicesImplementation/UpdateService.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Threading;
1212
using System.Threading.Tasks;
1313
using Windows.Services.Store;
14+
using Windows.Storage;
1415
using WinRT.Interop;
1516

1617
namespace Files.App.ServicesImplementation
@@ -178,6 +179,49 @@ public async Task CheckLatestReleaseNotesAsync(CancellationToken cancellationTok
178179
}
179180
}
180181

182+
public async Task CheckAndUpdateFilesLauncherAsync()
183+
{
184+
var destFolderPath = Path.Combine(UserDataPaths.GetDefault().LocalAppData, "Files");
185+
var destExeFilePath = Path.Combine(destFolderPath, "FilesLauncher.exe");
186+
187+
if (Path.Exists(destExeFilePath))
188+
{
189+
var hashEqual = false;
190+
var srcHashFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/FilesOpenDialog/FilesLauncher.exe.sha256"));
191+
var destHashFilePath = Path.Combine(destFolderPath, "FilesLauncher.exe.sha256");
192+
193+
if (Path.Exists(destHashFilePath))
194+
{
195+
using var srcStream = (await srcHashFile.OpenReadAsync()).AsStream();
196+
using var destStream = File.OpenRead(destHashFilePath);
197+
198+
hashEqual = HashEqual(srcStream, destStream);
199+
}
200+
201+
if (!hashEqual)
202+
{
203+
var srcExeFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/FilesOpenDialog/FilesLauncher.exe"));
204+
var destFolder = await StorageFolder.GetFolderFromPathAsync(destFolderPath);
205+
206+
await srcExeFile.CopyAsync(destFolder, "FilesLauncher.exe", NameCollisionOption.ReplaceExisting);
207+
await srcHashFile.CopyAsync(destFolder, "FilesLauncher.exe.sha256", NameCollisionOption.ReplaceExisting);
208+
209+
App.Logger.Info("FilesLauncher updated.");
210+
}
211+
}
212+
213+
bool HashEqual(Stream a, Stream b)
214+
{
215+
Span<byte> bufferA = stackalloc byte[64];
216+
Span<byte> bufferB = stackalloc byte[64];
217+
218+
a.Read(bufferA);
219+
b.Read(bufferB);
220+
221+
return bufferA.SequenceEqual(bufferB);
222+
}
223+
}
224+
181225
// WINUI3
182226
private static ContentDialog SetContentDialogRoot(ContentDialog contentDialog)
183227
{

src/Files.Backend/Services/IUpdateService.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,10 @@ public interface IUpdateService : INotifyPropertyChanged
3838
/// Gets release notes for the latest release
3939
/// </summary>
4040
Task<string?> GetLatestReleaseNotesAsync(CancellationToken cancellationToken = default);
41+
42+
/// <summary>
43+
/// Replace FilesLauncher.exe if it is used and has been updated
44+
/// </summary>
45+
Task CheckAndUpdateFilesLauncherAsync();
4146
}
4247
}

src/Files.OpenDialog/FilesLauncher/FilesLauncher.vcxproj

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@
189189
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
190190
</Link>
191191
<PostBuildEvent>
192-
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"</Command>
192+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"
193+
certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil"&gt;"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256"</Command>
193194
</PostBuildEvent>
194195
</ItemDefinitionGroup>
195196
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -211,7 +212,8 @@
211212
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
212213
</Link>
213214
<PostBuildEvent>
214-
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"</Command>
215+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"
216+
certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil"&gt;"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256"</Command>
215217
</PostBuildEvent>
216218
</ItemDefinitionGroup>
217219
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Sideload|Win32'">
@@ -233,7 +235,8 @@
233235
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
234236
</Link>
235237
<PostBuildEvent>
236-
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"</Command>
238+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"
239+
certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil"&gt;"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256"</Command>
237240
</PostBuildEvent>
238241
</ItemDefinitionGroup>
239242
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -251,7 +254,8 @@
251254
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
252255
</Link>
253256
<PostBuildEvent>
254-
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"</Command>
257+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"
258+
certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil"&gt;"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256"</Command>
255259
</PostBuildEvent>
256260
</ItemDefinitionGroup>
257261
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|arm64'">
@@ -269,7 +273,8 @@
269273
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
270274
</Link>
271275
<PostBuildEvent>
272-
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"</Command>
276+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"
277+
certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil"&gt;"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256"</Command>
273278
</PostBuildEvent>
274279
</ItemDefinitionGroup>
275280
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -291,7 +296,8 @@
291296
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
292297
</Link>
293298
<PostBuildEvent>
294-
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"</Command>
299+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"
300+
certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil"&gt;"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256"</Command>
295301
</PostBuildEvent>
296302
</ItemDefinitionGroup>
297303
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Sideload|x64'">
@@ -313,7 +319,8 @@
313319
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
314320
</Link>
315321
<PostBuildEvent>
316-
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"</Command>
322+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"
323+
certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil"&gt;"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256"</Command>
317324
</PostBuildEvent>
318325
</ItemDefinitionGroup>
319326
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|arm64'">
@@ -335,7 +342,8 @@
335342
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
336343
</Link>
337344
<PostBuildEvent>
338-
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"</Command>
345+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"
346+
certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil"&gt;"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256"</Command>
339347
</PostBuildEvent>
340348
</ItemDefinitionGroup>
341349
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Sideload|arm64'">
@@ -357,7 +365,8 @@
357365
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
358366
</Link>
359367
<PostBuildEvent>
360-
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"</Command>
368+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog"
369+
certutil -hashfile "$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName)" SHA256|findstr /R /V "^SHA256 ^CertUtil"&gt;"$(ProjectDir)..\..\..\src\Files.App\Assets\FilesOpenDialog\$(TargetFileName).sha256"</Command>
361370
</PostBuildEvent>
362371
</ItemDefinitionGroup>
363372
<ItemGroup>

0 commit comments

Comments
 (0)