From 82c6887326e65cac825a17c5c0ccff9feef3fda8 Mon Sep 17 00:00:00 2001 From: David Boike Date: Wed, 3 Dec 2025 15:41:58 -0600 Subject: [PATCH 1/2] Throw if 3rd-party security software removes a dependency during install --- .../FileSystem/FileUtils.cs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/ServiceControlInstaller.Engine/FileSystem/FileUtils.cs b/src/ServiceControlInstaller.Engine/FileSystem/FileUtils.cs index 1a505206ef..d3cccba7e4 100644 --- a/src/ServiceControlInstaller.Engine/FileSystem/FileUtils.cs +++ b/src/ServiceControlInstaller.Engine/FileSystem/FileUtils.cs @@ -1,6 +1,7 @@ namespace ServiceControlInstaller.Engine.FileSystem { using System; + using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; @@ -147,7 +148,25 @@ public static void UnzipToSubdirectory(string zipResourceName, string targetPath internal static void UnzipToSubdirectory(Stream zipStream, string targetPath) { - ZipFile.ExtractToDirectory(zipStream, targetPath, overwriteFiles: true); + using var archive = new ZipArchive(zipStream, ZipArchiveMode.Read, leaveOpen: true, entryNameEncoding: null); + archive.ExtractToDirectory(targetPath, overwriteFiles: true); + + // Validate 3rd-party security software didn't delete any of the files, but first, a small delay + // so that any tool out there has a chance to remove the file before prematurely declaring victory + Thread.Sleep(500); + foreach (var entry in archive.Entries) + { + var pathParts = entry.FullName.Split('/', '\\'); + var allParts = new string[pathParts.Length + 1]; + allParts[0] = targetPath; + Array.Copy(pathParts, 0, allParts, 1, pathParts.Length); + var destinationPath = Path.Combine(allParts); + var fileInfo = new FileInfo(destinationPath); + if (!fileInfo.Exists || fileInfo.Length != entry.Length) + { + throw new Exception($"The following file was removed after install, perhaps due to a false positive in a 3rd-party security tool. Add an exception for the path in the tool's configuration and try again: " + destinationPath); + } + } } static void RunWithRetries(Action action) From 76f5454dbf9ee974d50bbdb18ba1436cddd0f6d1 Mon Sep 17 00:00:00 2001 From: David Boike Date: Tue, 9 Dec 2025 12:07:26 -0600 Subject: [PATCH 2/2] Increase delay to 1s --- src/ServiceControlInstaller.Engine/FileSystem/FileUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ServiceControlInstaller.Engine/FileSystem/FileUtils.cs b/src/ServiceControlInstaller.Engine/FileSystem/FileUtils.cs index d3cccba7e4..ecc2c82cf6 100644 --- a/src/ServiceControlInstaller.Engine/FileSystem/FileUtils.cs +++ b/src/ServiceControlInstaller.Engine/FileSystem/FileUtils.cs @@ -153,7 +153,7 @@ internal static void UnzipToSubdirectory(Stream zipStream, string targetPath) // Validate 3rd-party security software didn't delete any of the files, but first, a small delay // so that any tool out there has a chance to remove the file before prematurely declaring victory - Thread.Sleep(500); + Thread.Sleep(1000); foreach (var entry in archive.Entries) { var pathParts = entry.FullName.Split('/', '\\');