#region Copyright 2010-2014 by Roger Knapp, Licensed under the Apache License, Version 2.0 /* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #endregion using System; using System.IO; using System.Diagnostics; using System.Text; using CSharpTest.Net.Crypto; namespace CSharpTest.Net.IO { /// /// Provides a class for managing a temporary directory and making reasonable a attempt to remove it upon disposal. /// [System.Diagnostics.DebuggerDisplay("{TempPath}")] public class TempDirectory : IDisposable { private string _temppath; /// /// Creates a new temp directory path that is not currently in use. /// /// [DebuggerNonUserCode] static string CreatePath() { int attempt = 0; while(true) { try { string path = Path.GetTempFileName(); if (File.Exists(path)) File.Delete(path); if (Directory.Exists(path)) throw new IOException(); Directory.CreateDirectory(path); return path; } catch (UnauthorizedAccessException) { if (++attempt < 10) continue; throw; } catch (IOException) { if(++attempt < 10) continue; throw; } } } /// /// Attaches a new instances of a TempFile to the provided directory path /// public static TempDirectory Attach(string existingPath) { return new TempDirectory(existingPath); } /// /// Safely delete the provided directory name /// public static void Delete(string path) { bool exists = false; try { exists = !String.IsNullOrEmpty(path) && Directory.Exists(path); } catch (IOException) { } if (exists) new TempDirectory(path).Dispose(); } /// /// Constructs a new temp directory with a newly created directory. /// public TempDirectory() : this(CreatePath()) { } /// /// Manage the provided directory path /// public TempDirectory(string directory) { TempPath = directory; } /// /// Removes the directory if Dispose() is not called /// ~TempDirectory() { try { Dispose(false); } catch { } } /// /// Returns the temporary directory path being managed. /// public string TempPath { [DebuggerNonUserCode] get { if (String.IsNullOrEmpty(_temppath)) throw new ObjectDisposedException(GetType().ToString()); return _temppath; } protected set { if (Exists) TempDirectory.Delete(_temppath); if (!String.IsNullOrEmpty(_temppath = value)) _temppath = Path.GetFullPath(_temppath); } } /// Disposes of the temporary directory public void Dispose() { Dispose(true); } /// /// Disposes of the temporary directory /// [DebuggerNonUserCode] protected virtual void Dispose(bool disposing) { try { if (_temppath != null && Exists) Directory.Delete(_temppath, true); _temppath = null; if (disposing) GC.SuppressFinalize(this); } catch (System.IO.IOException e) { string directoryname = _temppath; if (!disposing) //wait for next GC's collection { new TempFile(directoryname); _temppath = null; } Trace.TraceWarning("Unable to delete temp directory: {0}, reason: {1}", directoryname, e.Message); } } /// /// Detatches this instance from the temporary directory and returns the temp directory's path /// public string Detatch() { GC.SuppressFinalize(this); string name = _temppath; _temppath = null; return name; } /// /// Returns true if the current temp directory exists. /// [DebuggerNonUserCode] public bool Exists { get { return !String.IsNullOrEmpty(_temppath) && Directory.Exists(_temppath); } } /// /// Returns the FileInfo object for this temp directory. /// public DirectoryInfo Info { get { return new DirectoryInfo(TempPath); } } /// /// Deletes the current temp directory immediatly if it exists. /// public void Delete() { if (Exists) Directory.Delete(TempPath, true); } /// /// Copies the file content to the specified target file name /// public void CopyTo(string target) { DeepCopy(TempPath, target, false); } /// /// Copies the directory content to the specified target directory name /// public void CopyTo(string target, bool replace) { DeepCopy(TempPath, target, replace); } /// /// Creates a deep-copy of the directory contents /// public static void DeepCopy(string srcDirectory, string targetDirectory, bool replace) { Directory.CreateDirectory(targetDirectory); foreach(string file in Directory.GetFiles(srcDirectory)) File.Copy(file, Path.Combine(targetDirectory, Path.GetFileName(file)), replace); foreach (string dir in Directory.GetDirectories(srcDirectory)) DeepCopy(dir, Path.Combine(targetDirectory, Path.GetFileName(dir)), replace); } } }