2009-03-16 1 views
7

Можно ли открыть файл таким образом, который позволяет впоследствии удалить/переименовать его родительскую папку?Открыть файл без (действительно) его блокировки?

Я знаю, что вы можете сделать это:

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

который позволит для файла, который будет удален, когда файл закрывается дескриптор. Однако, если он не позволяет удалить родительскую папку без ошибок.

Я не нашел ничего в каркасе. Я что-то пропустил, или есть собственный API, с которым я могу взаимодействовать.

Примечание: Мне не важно, получилось ли исключение при использовании потока удалённого файла. На самом деле это было бы идеально.

UPDATE:

Таким образом, наиболее перспективная идея была Hardlink, но я просто не могу заставить его работать. Я все еще получаю доступ с правами доступа, когда пытаюсь удалить родительский каталог. Вот мой код:

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()); 
    } 
} 

ответ

0

Лучшее решение, которое я могу придумать, заключается в том, чтобы скопировать файл во временное место царапины. Затем откройте временный файл и удалите его, когда я закончу.

+0

Звучит как-то, что я сделал бы. Может быть, вы можете скопировать в память, если файл достаточно мал? – strager

+0

Да, мы делаем это сейчас, но есть много файлов, и они довольно большие 3Mb до 100Mb. Это вызывает много хлопок ГК. –

0

FileOpen использует CreateFile в Kernel32.dll. Я не уверен, что вы сможете достичь чего-то большего, чем предоставляет .NET framework, поскольку все параметры уже есть, если вы не выполняете его как transaction.

+0

Теперь я просматриваю документацию. Вы знаете, если файл, открытый с помощью CreateFileTransacted, позволяет удалить родительскую папку, или вы просто предлагаете его в качестве опции? –

+0

Я предполагаю, что в файле работает 2 потока, один для открытия и другой, пытающийся удалить одновременно? –

+0

Ну в конечном счете, но я контролирую только один из них. –

1

Если вы работаете с файловой системой NTFS, вы можете создать другую жесткую ссылку на файл во временном месте, вы избежите накладных расходов на файл, а первая ссылка должна быть удалена (либо сам файл, либо содержащий каталог), не выполняя второй.

+0

Хммм, это казалось очень многообещающим, однако я все еще получаю ошибку, когда удаляю родительскую папку. Может быть, я делаю что-то неправильно. Вы сами это пробовали? –

+0

Жесткие ссылки должны быть идентичны исходному файлу, то есть на самом деле нет понятия «основного» указателя на файл, все они работают одинаково. (он добавляет другой указатель каталога) Я лично не использовал их в этой конкретной ситуации, но он должен работать ... – Eric

+0

См. код, который я добавил, это не так. –