none
UnauthorizedAccessException / Code Example / Question for Reason / C#.NET RRS feed

  • Question

    Hi .NET Team,

    I've simulated 5 Threads writing and deleting (lock-scope Directory) files, I do get an UnauthorizedAccessException (access to the path ... is denied) without the integration of a delete-delay. Please have a look at my code, u may got an answer? it works for local SSD, but fails for external USB HDD, until i integrate a delete/exist-check delay.

    Best regards,

    Markus Sperl

    Exception:

    File does not exist on Delete, but File.Exists returns true

    [ image not displayable until account has been checked - i'm sorry ]

    Used Functions

    • File.AppendAllText
    • File.Exists
    • FileInfo.Delete

    My UnitTest Class:

        [TestClass]
        public class UnitTest1
        {
    
            private static readonly string data = new string('1', 512 * 1024); // 1024 byte =^ 1 kb -> 1 mb
    
            [TestMethod]
            public void TestWrite()
            {
                var root = @"E:\temp\archivetest";
                var fileName = "testdatei";
                var extension = ".txt";
                IList<Task> tasks = new List<Task>();
                for (int idx = 0; idx < 5; idx++) 
                {
                    var generatedFileName = string.Concat(fileName, idx, extension);
                    var filePath = Path.Combine(root, generatedFileName);
                    var thread = Task.Factory.StartNew( () => doWriteWork(filePath));
                    tasks.Add(thread);
    
                    Thread.Sleep(1000);
                }
    
                Task.WaitAll(tasks.ToArray());
            }
    
            private void doWriteWork(string filePath)
            {
                for (int i = 0; i < 1024 * 4; i++)
                {
                    ArchiveHelper.Write(filePath, data, ArchiveWriteMode.Append);
                }
            }
    
            public static void Main(string[] args)
            {
                new UnitTest1().TestWrite();
            }
        }

    Executed Code:

    public enum ArchiveWriteMode { Overwrite, Append } public class ArchiveHelper { private static ConcurrentDictionary<string, object> DirectorySyncRoot = new ConcurrentDictionary<string, object>(); private static Timer timer = new Timer(TryCleanUp, null, new TimeSpan(1, 0, 0), new TimeSpan(1, 0, 0)); /// <summary> /// used to limit the amount of ram used /// </summary> /// <param name="state"></param> private static void TryCleanUp(object state) { if (DirectorySyncRoot.Count > 100) DirectorySyncRoot.Clear(); } /// <summary> /// used to write content hard disk size managed into random files /// </summary> /// <param name="filePath"></param> /// <param name="content"></param> /// <param name="mode"></param> public static void Write(string filePath, string content, ArchiveWriteMode mode) { // needed for slower hdd's to wait for disk subsystem var freeDelay = 0; //global::Fill.Tools.Properties.Settings.Default.FreeDeleteDelay <= 1000 && global::Fill.Tools.Properties.Settings.Default.FreeDeleteDelay > 0 ? global::Fill.Tools.Properties.Settings.Default.FreeDeleteDelay : 0; // gather parent directory var parentDirectory = Directory.GetParent(filePath); // gather directory lock object var directoryLockObject = DirectorySyncRoot.GetOrAdd(parentDirectory.FullName, new object()); // gather drive size and trigger var driveId = Path.GetPathRoot(filePath); var drive = DriveInfo.GetDrives().FirstOrDefault(x => x.Name.Equals(driveId)); if (drive == null) { throw new Exception(string.Format("drive '{0}' not available", driveId)); } // gather parameters var limit = 0.01; //global::Fill.Tools.Properties.Settings.Default.FreeDriveSizePercent / 100.0; var fileCnt = 10; //global::Fill.Tools.Properties.Settings.Default.FreeFileCount; var extension = Path.GetExtension(filePath); var pattern = string.Concat("*", extension); lock (directoryLockObject) { // create directory if necessary if (!Directory.Exists(parentDirectory.FullName)) { Directory.CreateDirectory(parentDirectory.FullName); } // do the write operation switch (mode) { case ArchiveWriteMode.Append: File.AppendAllText(filePath, content); break; case ArchiveWriteMode.Overwrite: File.WriteAllText(filePath, content); break; } // and do cleanup if necessary var percentage = 1 - (double)drive.TotalFreeSpace / (double)drive.TotalSize; Console.WriteLine(string.Format("{0} > {1}", percentage, limit)); if (percentage > limit) { foreach (var file in parentDirectory.GetFiles(pattern, SearchOption.AllDirectories).OrderBy(x => x.LastWriteTime).Take(fileCnt)) {

    // QUESTION: why do I need this line? for USB HDD if (freeDelay > 0) Thread.Sleep(freeDelay); if (File.Exists(file.FullName)) { file.Delete(); Log.Warning(string.Format("deleted {0} due to lack of hard disk space", file.Name)); } } } } } }

    Wednesday, April 15, 2015 12:25 PM

Answers

  • Hello markus,

    >>it works for local SSD, but fails for external USB HDD, until i integrate a delete/exist-check delay.

    According to File.Delete Method: https://msdn.microsoft.com/en-us/library/system.io.file.delete(v=vs.110).aspx, if you check the File.Delete() and FileInfo.Delete would use similar code to delete the file.

    3 things would cause the UnauthorizedAccessException:

    The caller does not have the required permission.

    path is a directory.

    path specified a read-only file.

    From your description, I notice that you seems to put the folder to the USB, I am wondering if the running process has enough permission. You could run it as administrator.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, April 16, 2015 8:54 AM
    Moderator