Add improved file deletion code

This commit is contained in:
Timothy Baldridge 2020-03-19 06:13:57 -06:00
parent 387dff56f9
commit 86d5f7462a
2 changed files with 101 additions and 31 deletions

View File

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reactive.Subjects;
using System.Threading.Tasks;
using AlphaPath = Alphaleonis.Win32.Filesystem.Path;
namespace Wabbajack.Common
{
public class ProcessHelper
{
public enum StreamType
{
Output,
Error,
}
public string Path { get; set; }
public IEnumerable<object> Arguments { get; set; }
public bool LogError { get; set; } = true;
public readonly Subject<(StreamType Type, string Line)> Output = new Subject<(StreamType Type, string)>();
public ProcessHelper()
{
}
public async Task<int> Start()
{
var info = new ProcessStartInfo
{
FileName = (string)Path,
Arguments = string.Join(" ", Arguments),
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
var finished = new TaskCompletionSource<int>();
var p = new Process
{
StartInfo = info,
EnableRaisingEvents = true
};
p.Exited += (sender, args) =>
{
finished.SetResult(p.ExitCode);
};
p.OutputDataReceived += (sender, data) =>
{
if (string.IsNullOrEmpty(data.Data)) return;
Output.OnNext((StreamType.Output, data.Data));
};
p.ErrorDataReceived += (sender, data) =>
{
if (string.IsNullOrEmpty(data.Data)) return;
Output.OnNext((StreamType.Error, data.Data));
if (LogError)
Utils.Log($"{AlphaPath.GetFileName(Path)} ({p.Id}) StdErr: {data.Data}");
};
p.Start();
p.BeginErrorReadLine();
p.BeginOutputReadLine();
ChildProcessTracker.AddProcess(p);
try
{
p.PriorityClass = ProcessPriorityClass.BelowNormal;
}
catch (Exception)
{
// ignored
}
var result = await finished.Task;
Output.OnCompleted();
return result;
}
}
}

View File

@ -1214,41 +1214,21 @@ namespace Wabbajack.Common
/// delete a folder. If you don't like this code, it's unlikely to change without a ton of testing.
/// </summary>
/// <param name="path"></param>
public static void DeleteDirectory(string path)
public static async void DeleteDirectory(string path)
{
var info = new ProcessStartInfo
var process = new ProcessHelper
{
FileName = "cmd.exe",
Arguments = $"/c del /f /q /s \"{path}\" && rmdir /q /s \"{path}\" ",
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
Path = "cmd.exe",
Arguments = new object[] {"/c", "del", "/f", "/q", "/s", $"\"{path}\"", "&&", "rmdir", "/q", "/s", $"\"{path}\""},
};
var result = process.Output.Where(d => d.Type == ProcessHelper.StreamType.Output)
.ForEachAsync(p =>
{
Status($"Deleting: {p.Line}");
});
var p = new Process
{
StartInfo = info
};
p.Start();
ChildProcessTracker.AddProcess(p);
try
{
p.PriorityClass = ProcessPriorityClass.BelowNormal;
}
catch (Exception)
{
}
while (!p.HasExited)
{
var line = p.StandardOutput.ReadLine();
if (line == null) break;
Status(line);
}
p.WaitForExitAndWarn(TimeSpan.FromSeconds(30), $"Deletion process of {path}");
process.Start().Wait();
await result;
}
public static bool IsUnderneathDirectory(string path, string dirPath)