tags:

views:

674

answers:

4

Is it possible to open a file in a way that allows subsequent deletion/renaming of its parent folder?

I know you can do this:

File.Open("foo.bar", FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)

Which will allow for the file to be deleted when the file handle is closed. However, if it does not allow the parent folder to be deleted without error.

I couldn't find anything in the framework. Have I overlooked something, or is there a native API I can interop to.

Note: I don't care if I get an exception when using the stream of the deleted file. In fact that would be ideal.

UPDATE:

So the most promising idea was the Hardlink, however I just can't make it work. I still end up with Access Denied when i try to delete the parent directory. Here is my code:

class Program
{
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes);

    static void Main(string[] args)
    {
        string hardLinkPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
        string realPath = @"C:\foo\bar.txt";
        if (CreateHardLink(hardLinkPath, realPath, IntPtr.Zero))
        {
            using (FileStream stream = File.Open(hardLinkPath, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite))
            {
                Console.Write("File locked");
                Console.ReadLine();
            }

            File.Delete(hardLinkPath);
        }
        else
            Console.WriteLine("LastError:{0}", Marshal.GetLastWin32Error());
    }
}
A: 

The best solution I can come up with, is to copy the file to a temporary scratch location. Then, open the temp file, and delete it when I'm finished.

Greg Dean
Sounds like something I'd do. Maybe you can copy to memory if the file is small enough?
strager
yeah, we are doing that now, but there are lots of files, and they are fairly big 3Mb to 100Mb. It causes a lot of GC thrashing.
Greg Dean
A: 

I think you just asked a question and then promptly answered your own question.

SquidScareMe
The SO FAQ says this is fine
Brian R. Bondy
So is downvoting.
John Saunders
It's a valid answer to the question. I've got plenty of rep, downvote all you want..
Greg Dean
A: 

FileOpen uses CreateFile in Kernel32.dll. I'm not sure you'll be able to achieve anything more than the .NET framework provides you with, as all the options are already there, unless you perform it as a transaction.

Chris S
I'm fishing through the documentation now. Do you know if a file opened with CreateFileTransacted, allows for deletion of the parent folder, or are you just suggesting it as an option?
Greg Dean
I assume there's 2 threads working on the file, one to open and another trying to delete at the same time?
Chris S
Well ultimately, but I only control one of them.
Greg Dean
+1  A: 

If you're working with an NTFS you can create another hardlink to the file in a temporary location, you'll avoid the file copy overhead, and the first link should still be deletable (either the file itself or a containing directory) without effecting the second.

Eric
Hmmm, This seemed very promising, however I still get the error when i deleted the parent folder. Maybe I'm doing something wrong. Have you tried this yourself?
Greg Dean
Hard links should be identical to the original file, that is, there isn't really a concept of a "main" pointer to the file, they all work identically. (it adds another directory pointer) I haven't personally used them in this exact situation, but it should work...
Eric
See the code I added, this doesn't appear to be the case.
Greg Dean