private static void Cleanup() { string cleanupMarkerFile = Path.Combine(SupportFileDirBase, "CleanupNeeded"); var dirs = Directory.GetDirectories(SupportFileDirBase, "VER.*"); if (dirs.Length > 1) { // We will assume we should come and check again on our next launch. File.WriteAllText(cleanupMarkerFile, ""); foreach (string dir in Directory.GetDirectories(s_supportFileDirBase)) { // Don't clean up myself if (string.Compare(dir, s_supportFileDir, StringComparison.OrdinalIgnoreCase) == 0) { continue; } // We first try to move the directory and only delete it if that succeeds. // That way directories that are in use don't get cleaned up. try { var deletingName = dir + ".deleting"; if (dir.EndsWith(".deleting")) { deletingName = dir; } else { Directory.Move(dir, deletingName); } DirectoryUtilities.Clean(deletingName); } catch (Exception) { } } } else { // No cleanup needed, mark that fact FileUtilities.ForceDelete(cleanupMarkerFile); } }
/// <summary> /// Delete works much like File.Delete, except that it will succeed if the /// archiveFile does not exist, and will rename the archiveFile so that even if the archiveFile /// is locked the original archiveFile variable will be made available. /// /// It renames the archiveFile with a '[num].deleting'. These files might be left /// behind. /// /// It returns true if it was competely successful. If there is a *.deleting /// archiveFile left behind, it returns false. /// </summary> /// <param variable="fileName">The variable of the archiveFile to delete</param> public static bool ForceDelete(string fileName) { if (Directory.Exists(fileName)) { return(DirectoryUtilities.Clean(fileName) != 0); } if (!File.Exists(fileName)) { return(true); } // First move the archiveFile out of the way, so that even if it is locked // The original archiveFile is still gone. string renamedFile; int i = 0; for (i = 0; ; i++) { renamedFile = fileName + "." + i.ToString() + ".deleting"; if (!File.Exists(renamedFile)) { break; } } File.Move(fileName, renamedFile); bool ret = TryDelete(renamedFile); if (i > 0) { // delete any old *.deleting files that may have been left around string deletePattern = Path.GetFileName(fileName) + @".*.deleting"; foreach (string deleteingFile in Directory.GetFiles(Path.GetDirectoryName(fileName), deletePattern)) { TryDelete(deleteingFile); } } return(ret); }
/// <summary> /// DirectoryUtilities.GetFiles is basicaly the same as Directory.GetFiles /// however it returns IEnumerator, which means that it lazy. This is very important /// for large directory trees. A searchPattern can be specified (Windows wildcard conventions) /// that can be used to filter the set of archiveFile names returned. /// /// Suggested Usage /// /// foreach(string fileName in DirectoryUtilities.GetFiles("c:\", "*.txt")){ /// Console.WriteLine(fileName); /// } /// /// </summary> /// <param variable="directoryPath">The base directory to enumerate</param> /// <param variable="searchPattern">A pattern to filter the names (windows filename wildcards * ?)</param> /// <param variable="searchOptions">Indicate if the search is recursive or not. </param> /// <returns>The enumerator for all archiveFile names in the directory (recursively). </returns> public static IEnumerable <string> GetFiles(string directoryPath, string searchPattern, SearchOption searchOptions) { string[] fileNames = Directory.GetFiles(directoryPath, searchPattern, SearchOption.TopDirectoryOnly); Array.Sort <string>(fileNames, StringComparer.OrdinalIgnoreCase); foreach (string fileName in fileNames) { yield return(fileName); } if (searchOptions == SearchOption.AllDirectories) { string[] subDirNames = Directory.GetDirectories(directoryPath); Array.Sort <string>(subDirNames); foreach (string subDir in subDirNames) { foreach (string fileName in DirectoryUtilities.GetFiles(subDir, searchPattern, searchOptions)) { yield return(fileName); } } } }
/// <summary> /// Unpacks any resource that begings with a .\ (so it looks like a relative path name) /// Such resources are unpacked into their relative position in SupportFileDir. /// 'force' will force an update even if the files were unpacked already (usually not needed) /// The function returns true if files were unpacked. /// </summary> public static bool UnpackResourcesIfNeeded(bool force = false) { var filesExist = Directory.Exists(SupportFileDir); if (filesExist) { if (force) { filesExist = false; DirectoryUtilities.Clean(SupportFileDir); UnpackResources(); } } else { UnpackResources(); } // Do we need to cleanup old files? if (filesExist && File.Exists(Path.Combine(SupportFileDirBase, "CleanupNeeded"))) { Cleanup(); } // Register a Assembly resolve event handler so that we find our support dlls in the support dir. AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args) { var simpleName = args.Name; var commaIdx = simpleName.IndexOf(','); if (0 <= commaIdx) { simpleName = simpleName.Substring(0, commaIdx); } string fileName = Path.Combine(SupportFileDir, simpleName + ".dll"); if (File.Exists(fileName)) { return(System.Reflection.Assembly.LoadFrom(fileName)); } fileName = Path.Combine(SupportFileDir, simpleName + ".exe"); if (File.Exists(fileName)) { return(System.Reflection.Assembly.LoadFrom(fileName)); } // Also look in processor specific location fileName = Path.Combine(SupportFileDir, ProcessArch, simpleName + ".dll"); if (File.Exists(fileName)) { return(System.Reflection.Assembly.LoadFrom(fileName)); } // And look for an exe (we need this for HeapDump.exe) fileName = Path.Combine(SupportFileDir, ProcessArch, simpleName + ".exe"); if (File.Exists(fileName)) { return(System.Reflection.Assembly.LoadFrom(fileName)); } return(null); }; return(!filesExist); }