C#报”UnauthorizedAccessException”的原因以及解决办法

  • Post category:C#

当.Net应用程序在尝试访问文件或目录时,如果它没有权限,它会引发UnauthorizedAccessException异常。通常,这会发生在以下情况下:

  1. 当应用程序以不具备访问文件或目录所需权限的用户身份运行时。
  2. 当正在写入文件的目录被设置为只读模式时。
  3. 文件被占用或被其他进程锁定时。
  4. 当尝试访问加密文件(EFS)时。

解决步骤如下:

  1. 确保应用程序以具备访问目标文件或目录所需权限的用户身份运行。例如,如果应用程序需要写入文件,则必须确保应用程序正在运行的用户具有写入目标文件所在的目录的权限。
  2. 确保目标目录不是只读的。您可以通过右键单击目标文件夹并选择“属性”来验证目录的只读状态。如果“只读”选项被选中,则应该取消选中该选项以允许写入目录。
  3. 如果文件被占用或被其他进程锁定,则需要等待占用文件的进程释放文件句柄。如果无法确定哪个进程占用了文件,请使用第三方工具,例如Process Explorer来诊断问题。
  4. 如果文件是加密文件(EFS),则必须确保应用程序正在运行的用户拥有访问该文件的加密证书。您可以使用EFS Recovery Agent(Recovery Agent)证书或加密数据恢复代理(DRA)证书授权其他帐户访问加密文件。

以下是两个示例,用于解决UnauthorizedAccessException异常:

示例1

单击查看

“`csharp
try
{
string fileName = @”C:\Temp\TestFile.txt”;
File.WriteAllText(fileName, “Test Data”);
}
catch (UnauthorizedAccessException ex)
{
//检查当前用户是否具备写入目标目录的权限
//检查目标目录是否被设置为只读模式
}
“`

该代码尝试在`C:\Temp`目录中创建一个新文件,并向该文件写入数据。如果执行时发生`UnauthorizedAccessException`异常,需要检查当前用户是否具备向该目录写入文件的权限,或者该目录是否被设置为只读模式。可以使用`File.SetAttributes`方法,将目录属性更改为不只读。例如:

“`csharp
string targetDir = @”C:\Temp”;
FileAttributes attributes = File.GetAttributes(targetDir);
attributes = attributes & ~FileAttributes.ReadOnly;
File.SetAttributes(targetDir, attributes);
“`

示例2

单击查看

“`csharp
try
{
string fileName = @”C:\Temp\LockedFile.txt”;
FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
using (StreamWriter writer = new StreamWriter(fileStream))
{
writer.Write(“Test Data”);
}
}
catch (UnauthorizedAccessException ex)
{
//等待占用文件的进程释放文件句柄
//使用Process Explorer查看占用文件的进程
}
“`

该代码尝试访问`C:\Temp\LockedFile.txt`,并在该文件中写入数据。如果尝试在文件被占用时执行此操作,将会引发`UnauthorizedAccessException`异常。解决此问题的最佳方法是循环检查文件是否还在被占用,并等待其释放。您也可以使用第三方工具,例如[Process Explorer](https://docs.microsoft.com/zh-cn/sysinternals/downloads/process-explorer),来诊断文件是否被占用,并查看占用文件的进程。例如,您可以使用以下代码等待文件释放:

“`csharp
string lockedFileName = @”C:\Temp\LockedFile.txt”;
while (FileIsLocked(lockedFileName))
{
Thread.Sleep(1000); //等待1秒
}

private bool FileIsLocked(string fileName)
{
FileStream stream = null;

try
{
stream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
stream.Close();
}
catch (IOException ex)
{
return true; //文件被锁定
}
finally
{
if (stream != null)
{
stream.Close();
}
}

return false; //文件未被锁定
}
“`