C# Directory.Delete 不起作用。访问被拒绝错误,但在 Windows 资源管理器下它没问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1701457/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Directory.Delete doesn't work. Access denied error but under Windows Explorer it's ok
提问by binball
I have searched the SO but find nothing.
我已经搜索了 SO 但什么也没找到。
Why this doesn't work?
为什么这不起作用?
Directory.Delete(@"E:\{90120000-001A-0000-0000-0000000FF1CE}-C");
Above line will throw exception "Access is denied". I have admin rigths and I can delete the dir with Explorer.
以上行将抛出异常“访问被拒绝”。我有管理员权限,可以使用资源管理器删除该目录。
It looks like some forbidden chars? but Windows Explorer can handle it. How can I delete directories with names like that?
它看起来像一些禁止的字符?但 Windows 资源管理器可以处理它。如何删除具有类似名称的目录?
采纳答案by binball
Thank you all for your input, it helps me in quick find of solution.
感谢大家的投入,它帮助我快速找到解决方案。
As Phil mentioned "Directory.Delete fails if it is, regardless of permissions (see bottom of msdn.microsoft.com/en-us/library/…)"
正如 Phil 所提到的“Directory.Delete 会失败,无论权限如何(请参阅 msdn.microsoft.com/en-us/library/... 的底部)”
In addition Unable to remove Read-Only attribute from folderMicrosoft says:
此外无法从文件夹中删除只读属性微软说:
You may be unable to remove the Read-Only attribute from a folder using Windows Explorer. In addition, some programs may display error messages when you try to save files to the folder.
您可能无法使用 Windows 资源管理器从文件夹中删除只读属性。此外,当您尝试将文件保存到文件夹时,某些程序可能会显示错误消息。
Conclusion: always remove all dir,file attributes diffrent then Normal before deleting. So below code solve the problem:
结论:在删除之前始终删除所有目录,文件属性与 Normal 不同。所以下面的代码解决了这个问题:
System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(@"E:\{90120000-0021-0000-0000-0000000FF1CE}-C1");
if (dir.Exists)
{
setAttributesNormal(dir);
dir.Delete(true);
}
. . .
function setAttributesNormal(DirectoryInfo dir) {
foreach (var subDir in dir.GetDirectories())
setAttributesNormal(subDir);
foreach (var file in dir.GetFiles())
{
file.Attributes = FileAttributes.Normal;
}
}
回答by Scott
Have you tried to create a new instance of the DirectoryInfoclass, and then checking the exists before the delete? The code would look like this:
您是否尝试过创建DirectoryInfo类的新实例,然后在删除之前检查是否存在?代码如下所示:
System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(@"E:\{90120000-001A-0000-0000-0000000FF1CE}-C");
if (dir.Exists)
dir.Delete(true);
Also, please verify that you (the user running the application) has access to the folder. If this is a network mapped drive, it will need to be able to be deleted by the user running the application.
此外,请验证您(运行应用程序的用户)是否有权访问该文件夹。如果这是网络映射驱动器,则需要能够被运行应用程序的用户删除。
Hope this helps!
希望这可以帮助!
回答by jheddings
Based on the directory you are working in, you will probably need administrator access to delete files. To test this, run your app as administrator from explorer and see if it works (right-click the .exe and choose "Run As Administrator").
根据您工作的目录,您可能需要管理员权限才能删除文件。要对此进行测试,请从资源管理器中以管理员身份运行您的应用程序并查看它是否有效(右键单击 .exe 并选择“以管理员身份运行”)。
If that works, you'll need to get administrator privileges when your application executes. You can do this by adding the following to your application manifest:
如果可行,您将需要在应用程序执行时获得管理员权限。您可以通过将以下内容添加到您的应用程序清单中来做到这一点:
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" />
</requestedPrivileges>
</security>
</trustInfo>
回答by mtd
I had this symptom, and it actually was explorer.exe itself that was locking the directory. I found this using handle.exe, but one can also use powershell to find which process is locking the file:
我有这个症状,实际上是 explorer.exe 本身锁定了目录。我使用handle.exe发现了这一点,但也可以使用 powershell 来查找哪个进程正在锁定文件:
$lockedFile = "C:\Windows\System32\wshtcpip.dll"
Get-Process | foreach{$processVar = $_; $_.Modules | foreach { if ($_.FileName -like "${lockedFile}*") { $processVar.Name + " PID:" + $processVar.id + " [" + $_.Filename + "]"}}}
You then have to decide whether to try to stop that process gracefully or not; it would be easy to modify the powershell script to try to kill any processes locking the file:
然后,您必须决定是否尝试优雅地停止该过程;修改powershell脚本以尝试杀死锁定文件的任何进程很容易:
$lockedFile = "C:\directory_I_want_to_delete"
Get-Process | foreach{$processVar = $_; $_.Modules | foreach { if ($_.FileName -like "${lockedFile}*") { write-host $processVar.Name + " PID:" + $processVar.id + " [" + $_.Filename + "]" ; write-host "Killing process..." ; stop-process -pid $processVar.id -force }}}
回答by Chuck
I used binball's code and added one line to set the directory attributes to normal also.
我使用 binball 的代码并添加了一行来将目录属性也设置为正常。
if (dir.Exists)
{
setAttributesNormal(dir);
dir.Delete(true);
}
function setAttributesNormal(DirectoryInfo dir)
{
foreach (var subDir in dir.GetDirectories())
{
setAttributesNormal(subDir);
subDir.Attributes = FileAttributes.Normal;
}
foreach (var file in dir.GetFiles())
{
file.Attributes = FileAttributes.Normal;
}
}
回答by Keombre
Adding to @binball and @Chuck answer. Here is a somewhat quick async-friendly implementation of setAttributesNormal()
using BFS to traverse directories.
It's ideal for deep directory traversal, where recursion may fill call stack.
添加到@binball 和@Chuck 答案。这是一个setAttributesNormal()
使用 BFS 遍历目录的快速异步友好实现。它非常适合深度目录遍历,其中递归可能会填满调用堆栈。
internal static void SetAttributesNormal(DirectoryInfo path) {
// BFS folder permissions normalizer
Queue<DirectoryInfo> dirs = new Queue<DirectoryInfo>();
dirs.Enqueue(path);
while (dirs.Count > 0) {
var dir = dirs.Dequeue();
dir.Attributes = FileAttributes.Normal;
Parallel.ForEach(dir.EnumerateFiles(), e => e.Attributes = FileAttributes.Normal);
foreach (var subDir in dir.GetDirectories())
dirs.Enqueue(subDir);
}
}