BizHawk/BizHawk.Common/TempFileManager.cs

101 lines
2.5 KiB
C#

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
namespace BizHawk.Common
{
/// <summary>
/// Starts a thread which cleans any filenames in %temp% beginning with bizhawk.bizdelete.
/// Files shouldn't be named that unless they're safe to delete, but notably, they may stil be in use. That won't hurt this component.
/// When they're no longer in use, this component will then be able to delete them.
/// </summary>
public static class TempFileCleaner
{
// TODO - manage paths other than %temp%, make not static, or allow adding multiple paths to static instance
public static string GetTempFilename(string friendlyname, string extension = null, bool delete = true)
{
string guidPart = Guid.NewGuid().ToString();
var fname = $"biz-{System.Diagnostics.Process.GetCurrentProcess().Id}-{friendlyname}-{guidPart}{extension ?? ""}";
if (delete)
{
fname = RenameTempFilenameForDelete(fname);
}
return Path.Combine(Path.GetTempPath(), fname);
}
public static string RenameTempFilenameForDelete(string path)
{
string filename = Path.GetFileName(path);
string dir = Path.GetDirectoryName(path);
if (!filename.StartsWith("biz-"))
{
throw new InvalidOperationException();
}
filename = "bizdelete-" + filename.Remove(0, 4);
return Path.Combine(dir, filename);
}
public static void Start()
{
lock (typeof(TempFileCleaner))
{
if (thread != null)
{
return;
}
thread = new Thread(ThreadProc)
{
IsBackground = true,
Priority = ThreadPriority.Lowest
};
thread.Start();
}
}
#if WINDOWS
[DllImport("kernel32.dll", EntryPoint = "DeleteFileW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
static extern bool DeleteFileW([MarshalAs(UnmanagedType.LPWStr)]string lpFileName);
#endif
static void ThreadProc()
{
var di = new DirectoryInfo(Path.GetTempPath());
for (;;)
{
var fis = di.GetFiles("bizdelete-*");
foreach (var fi in fis)
{
try
{
// SHUT. UP. THE. EXCEPTIONS.
#if WINDOWS
DeleteFileW(fi.FullName);
#else
fi.Delete();
#endif
}
catch
{
}
// try not to do more than one thing per frame
Thread.Sleep(100);
}
// try not to slam the filesystem too hard, we dont want this to cause any hiccups
Thread.Sleep(5000);
}
}
public static void Stop()
{
}
static Thread thread;
}
}