using System; using System.IO; using System.Runtime.InteropServices; namespace BizHawk.Common { /// /// 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. /// 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 = string.Format("biz-{0}-{1}-{2}{3}", 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 System.Threading.Thread(ThreadProc); thread.IsBackground = true; thread.Priority = System.Threading.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 System.Threading.Thread.Sleep(100); } //try not to slam the filesystem too hard, we dont want this to cause any hiccups System.Threading.Thread.Sleep(5000); } } public static void Stop() { } static System.Threading.Thread thread; } }