Skip to content

Commit

Permalink
Delete files while respecting dry-run, verbosity
Browse files Browse the repository at this point in the history
  • Loading branch information
nirbar committed Sep 25, 2024
1 parent 5e64812 commit 60e63e5
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 171 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ on:
version:
description: 'Build & package version'
required: true
default: 0.2.3
default: 0.2.4
type: string
jobs:
Build:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,4 @@ paket-files/
__pycache__/
*.pyc
/build/
launchSettings.json
48 changes: 24 additions & 24 deletions MsiZapEx/BundleInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,37 +108,37 @@ private static List<BundleInfo> FindByUpgradeCode(Guid bundleUpgradeCode, Regist

public void Prune()
{
using (RegistryModifier modifier = new RegistryModifier())
using (RegistryModifier registryModifier = new RegistryModifier())
{
if (!BundleProductCode.Equals(Guid.Empty))
using (FileSystemModifier fileSystemModifier = new FileSystemModifier())
{
modifier.DeferDeleteKey(RegistryHive.LocalMachine, RegistryView, $@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{BundleProductCode.ToString("B")}");

foreach (string d in Dependents)
{
modifier.DeferDeleteKey(RegistryHive.ClassesRoot, RegistryView.Registry64, $@"Installer\Dependencies\{d}\Dependents\{BundleProductCode.ToString("B")}");
}
}
if (!string.IsNullOrEmpty(BundleProviderKey))
{
modifier.DeferDeleteKey(RegistryHive.ClassesRoot, RegistryView.Registry64, $@"Installer\Dependencies\{BundleProviderKey}");
Prune(fileSystemModifier, registryModifier);
}
}
}

// Remove bundle from PendingFileRenameOperations
if (!string.IsNullOrEmpty(BundleCachePath))
{
//TODO Use FileSystemModifier
try
{
File.Delete(BundleCachePath);
}
catch (Exception ex)
{
internal void Prune(FileSystemModifier fileSystemModifier, RegistryModifier registryModifier)
{
if (!BundleProductCode.Equals(Guid.Empty))
{
registryModifier.DeferDeleteKey(RegistryHive.LocalMachine, RegistryView, $@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{BundleProductCode.ToString("B")}");

}
modifier.DeferRemoveFromPendingOperations(BundleCachePath);
foreach (string d in Dependents)
{
registryModifier.DeferDeleteKey(RegistryHive.ClassesRoot, RegistryView.Registry64, $@"Installer\Dependencies\{d}\Dependents\{BundleProductCode.ToString("B")}");
}
}
if (!string.IsNullOrEmpty(BundleProviderKey))
{
registryModifier.DeferDeleteKey(RegistryHive.ClassesRoot, RegistryView.Registry64, $@"Installer\Dependencies\{BundleProviderKey}");
}

// Remove bundle from PendingFileRenameOperations
if (!string.IsNullOrEmpty(BundleCachePath))
{
registryModifier.DeferRemoveFromPendingOperations(BundleCachePath);
fileSystemModifier.DeferDeleteFolder(Path.GetDirectoryName(BundleCachePath));
}
}

internal void PrintState()
Expand Down
80 changes: 80 additions & 0 deletions MsiZapEx/FileSystemModifier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.IO;

namespace MsiZapEx
{
class FileSystemModifier : IDisposable
{
private List<string> _deleteFolders = new List<string>();
private List<string> _deleteFiles = new List<string>();

public void Dispose()
{
foreach (string folder in _deleteFolders)
{
DeleteFolder(folder);
}
_deleteFolders.Clear();
foreach (string file in _deleteFiles)
{
DeleteFile(file);
}
_deleteFiles.Clear();
}

private void DeleteFile(string path)
{
if (!File.Exists(path))
{
return;
}

if ((Settings.Instance?.DryRun == true) || (Settings.Instance?.Verbose == true))
{
Console.WriteLine($"Delete file '{path}'");
if (Settings.Instance?.DryRun == true)
{
return;
}
}

File.SetAttributes(path, FileAttributes.Normal);
File.Delete(path);
}

private void DeleteFolder(string path)
{
if (!Directory.Exists(path))
{
return;
}

if ((Settings.Instance?.DryRun == true) || (Settings.Instance?.Verbose == true))
{
Console.WriteLine($"Delete folder '{path}'");
if (Settings.Instance?.DryRun == true)
{
return;
}
}

IEnumerable<string> files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories);
foreach (string file in files)
{
DeleteFile(file);
}
Directory.Delete(path, true);
}

public void DeferDeleteFile(string path)
{
_deleteFiles.Add(path);
}

public void DeferDeleteFolder(string path)
{
_deleteFolders.Add(path);
}
}
}
28 changes: 10 additions & 18 deletions MsiZapEx/ProductInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,45 +341,37 @@ private void Read(string obfuscatedGuid, bool? machineScope)
}
}

internal void Prune(RegistryModifier modifier)
internal void Prune(FileSystemModifier fileSystemModifier, RegistryModifier registryModifier)
{
foreach (ComponentInfo c in Components)
{
c.Prune(ProductCode, modifier);
c.Prune(ProductCode, registryModifier);
}
foreach (PatchInfo p in Patches)
{
p.Prune(ProductCode, modifier);
p.Prune(ProductCode, registryModifier);
}

string obfuscatedProductCode = GuidEx.MsiObfuscate(ProductCode);
modifier.DeferDeleteKey(RegistryHive.LocalMachine, RegistryView.Registry64, $@"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\{UserSID}\Products\{obfuscatedProductCode}");
modifier.DeferDeleteKey(RegistryHive.LocalMachine, View, $@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{ProductCode.ToString("B")}");
registryModifier.DeferDeleteKey(RegistryHive.LocalMachine, RegistryView.Registry64, $@"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\{UserSID}\Products\{obfuscatedProductCode}");
registryModifier.DeferDeleteKey(RegistryHive.LocalMachine, View, $@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{ProductCode.ToString("B")}");

string keyBase = MachineScope ? @"SOFTWARE\Classes" : @"Software\Microsoft";
RegistryHive hiveBase = MachineScope ? RegistryHive.LocalMachine : RegistryHive.CurrentUser;
modifier.DeferDeleteKey(hiveBase, RegistryView.Registry64, $@"{keyBase}\Installer\Products\{obfuscatedProductCode}");
modifier.DeferDeleteKey(hiveBase, RegistryView.Registry64, $@"{keyBase}\Installer\Features\{obfuscatedProductCode}");
registryModifier.DeferDeleteKey(hiveBase, RegistryView.Registry64, $@"{keyBase}\Installer\Products\{obfuscatedProductCode}");
registryModifier.DeferDeleteKey(hiveBase, RegistryView.Registry64, $@"{keyBase}\Installer\Features\{obfuscatedProductCode}");

// Dependencies
modifier.DeferDeleteKey(hiveBase, RegistryView.Registry64, $@"SOFTWARE\Classes\Installer\Dependencies\{ProductCode.ToString("B")}");
registryModifier.DeferDeleteKey(hiveBase, RegistryView.Registry64, $@"SOFTWARE\Classes\Installer\Dependencies\{ProductCode.ToString("B")}");

foreach (string d in Dependants)
{
modifier.DeferDeleteKey(hiveBase, RegistryView.Registry64, $@"SOFTWARE\Classes\Installer\Dependencies\{d}\Dependents\{ProductCode.ToString("B")}");
registryModifier.DeferDeleteKey(hiveBase, RegistryView.Registry64, $@"SOFTWARE\Classes\Installer\Dependencies\{d}\Dependents\{ProductCode.ToString("B")}");
}

//TODO Use FileSystemModifier
if (!string.IsNullOrEmpty(LocalPackage))
{
try
{
File.Delete(LocalPackage);
}
catch (Exception ex)
{

}
fileSystemModifier.DeferDeleteFile(LocalPackage);
}
}
}
Expand Down
Loading

0 comments on commit 60e63e5

Please sign in to comment.