如何标记“正在使用”的目录,以便无法删除或重命名?

时间:2018-03-30 20:32:09

标签: c# .net filesystems

我正在编写一个封装临时文件夹的类。该文件夹将在程序与它们一起使用时保存文件,然后在处理对象时自行删除。

我想防止临时文件夹在使用时被搞砸。我知道可以在不更改任何权限的情况下保持文件夹“锁定” - 例如,如果打开命令提示符并将工作目录设置为特定文件夹,则无法删除该文件夹,除非您关闭命令提示符或将工作目录更改为其他内容。有没有办法在c#中以编程方式执行此操作?

我知道这有可能:

var path = @"c:\temp\MyFolderName";
System.IO.Directory.CreateDirectory(path);
System.Environment.CurrentDirectory = path;
System.IO.Directory.Delete(path); //Throws error

...但是这限制了我一个工作文件夹(看起来有点像kludgy)。

我知道我们可以通过打开它来锁定文件,但似乎没有办法“打开”目录。

2 个答案:

答案 0 :(得分:3)

最直接的方法是在该目录中创建临时文件并将其锁定(使用FileShare.None打开):

var directory = @"G:\tmp\so\locked";
var fileHandle = new FileStream(
    Path.Combine(directory, ".lock"), 
    FileMode.Create, 
    FileAccess.ReadWrite, 
    FileShare.None);            
try {
    // now, you cannot delete or rename that folder until you press a key
    Console.ReadKey();
}
finally {
    fileHandle.Dispose();
}

如果由于某种原因不满足您 - 您可以获取目录本身的句柄。我不知道用纯.NET做到这一点的方法,但是你可以用原生的winapi(CreateFile来做到这一点,但是尽管它的名字,它不会创建文件或目录,只需获取句柄):

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false)]
private static extern SafeFileHandle CreateFile(string lpFileName, FileAccess dwDesiredAccess, FileShare dwShareMode, IntPtr securityAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);

var directory = @"G:\tmp\so\locked";
var directoryHandle = CreateFile(
    directory, 
    FileAccess.ReadWrite, 
    FileShare.Read, 
    IntPtr.Zero, 
    FileMode.Open, 
    0x02000000, // << this flag is needed to obtain handle to directory
    IntPtr.Zero);
if (directoryHandle.IsInvalid)
    throw new Exception("Failed to obtain handle to directory");
try {
    Console.ReadKey();
}
finally {
    directoryHandle.Dispose();
}

它会产生相同的效果(在释放句柄之前无法删除或重命名目录),但没有其他文件。

答案 1 :(得分:-3)

System.Security.AccessControl

中有DirectorySecurity个班级

直接从文档中获取的示例:

AddDirectorySecurity(DirectoryName, @"MYDOMAIN\MyAccount", FileSystemRights.ReadData, AccessControlType.Allow);

public static void AddDirectorySecurity(string FileName, string Account, FileSystemRights Rights, AccessControlType ControlType)
{
      // Create a new DirectoryInfo object.
      DirectoryInfo dInfo = new DirectoryInfo(FileName);

      // Get a DirectorySecurity object that represents the 
      // current security settings.
      DirectorySecurity dSecurity = dInfo.GetAccessControl();

      // Add the FileSystemAccessRule to the security settings. 
      dSecurity.AddAccessRule(new FileSystemAccessRule(Account, Rights, ControlType));

      // Set the new access settings.
      dInfo.SetAccessControl(dSecurity);
}