Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undo DeleteOnClose on FileStream

Tags:

c#

I'm having a class that is using a FileStream internally using the FileOption: DeleteOnClose. The normal behavior is when I allocate the class with a filename, I do not use the DeleteOnClose, otherwise I use it.

The only problem is that I happens sometimes that I need to undo the DeleteOnClose.

I would be too lengthy to explain the deeper details here. Of course I could create a copy and copy the contents of the FileStream that have been opened with DeleteOnClose to another FileStream but the file size is too large (>= 30GB) so that this approach is impractical.

Deleting the file manually does not work, since the classes are more or less used as memory containers that need to be handled by the GC. Also when something happens it's not helpful to have dead files lying around.

So I was hoping if there is a way to undo the DeleteOnClose attribute as this can be done, e.g. with SetFileAttributes where e.g. the Temporary flag can be set/unset.

With the comments of TheGeneral and TonPlooij I created a small example to test FileDispositionInfo, but somehow this also doesn't work (copied from http://source.roslyn.codeplex.com/#Roslyn.Test.Utilities/TempFiles/DisposableFile.cs,4d5c94058d1b4cd3):

using Microsoft.Win32.SafeHandles;
using System;
using System.IO;
using System.Runtime.InteropServices;

namespace ConsoleApp11
{
    class Program
    {
        [DllImport("kernel32.dll", PreserveSig = false)]
        private static extern void SetFileInformationByHandle(SafeFileHandle handle, int fileInformationClass, ref uint fileDispositionInfoDeleteFile, int bufferSize);

        private const int FileDispositionInfo = 4;

        internal static void PrepareDeleteOnCloseStreamForDisposal(FileStream stream)
        {
            // tomat: Set disposition to "delete" on the stream, so to avoid ForeFront EndPoint
            // Protection driver scanning the file. Note that after calling this on a file that's open with DeleteOnClose, 
            // the file can't be opened again, not even by the same process.
            uint trueValue = 1;
            SetFileInformationByHandle(stream.SafeFileHandle, FileDispositionInfo, ref trueValue, sizeof(uint));
        }

        /// <summary>
        /// Marks given file for automatic deletion when all its handles are closed.
        /// Note that after doing this the file can't be opened again, not even by the same process.
        /// </summary>
        internal static void DeleteFileOnClose(string fullPath)
        {
            using (var stream = new FileStream(fullPath, FileMode.Create,  FileAccess.ReadWrite, FileShare.Delete| FileShare.ReadWrite, 8))
            {
                PrepareDeleteOnCloseStreamForDisposal(stream);
            }
        }
        static void Main(string[] args)
        {       
            DeleteFileOnClose("D:\\test.dat");

            Console.WriteLine("Done.");
            Console.ReadKey();
        }
    }
}
like image 521
msedi Avatar asked Dec 01 '25 01:12

msedi


1 Answers

To answer you question directly, no you cant change the option mid way through. The file stream uses the winapi flag FILE_FLAG_DELETE_ON_CLOSE, this cant be changed mid way through, its essentially associated with the file handle, when the handle is closed the operating system cleans up the file, that is it and no work around.

If you want different behavior you will have to implement it yourself after the fact. ie deleting the file after its closed or not.

like image 134
TheGeneral Avatar answered Dec 02 '25 14:12

TheGeneral



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!