C# Directory.Move():对路径的访问被拒绝

C# Directory.Move():对路径的访问被拒绝,c#,exception-handling,directory,access-denied,C#,Exception Handling,Directory,Access Denied,我正在Visual Studio 2010中使用C#编写此Windows窗体应用程序 表单上有一个执行按钮,用户将点击该按钮,程序将生成一些文件并存储在输出文件夹中(该文件夹由程序使用目录.CreateDirectory()创建) 我想创建一个存档文件夹来保存以前运行的输出文件 在每次运行开始时,我尝试将现有的Output文件夹移动到Archive文件夹,然后创建一个新的Output文件夹。下面是我运行的移动目录的函数 static void moveToArchive() { if (

我正在Visual Studio 2010中使用C#编写此Windows窗体应用程序

表单上有一个执行按钮,用户将点击该按钮,程序将生成一些文件并存储在
输出
文件夹中(该文件夹由程序使用
目录.CreateDirectory()
创建)

我想创建一个存档文件夹来保存以前运行的输出文件

在每次运行开始时,我尝试将现有的
Output
文件夹移动到
Archive
文件夹,然后创建一个新的
Output
文件夹。下面是我运行的移动目录的函数

static void moveToArchive()
{
    if (!Directory.Exists("Archive")) Directory.CreateDirectory("Archive");
    string timestamp = DateTime.Now.ToString("yyyyMMddHHmms");
    try
    {
        Directory.Move("Output", "Archive\\" + timestamp);
    }
    catch(Exception e)
    {
        Console.WriteLine("Can not move folder: " + e.Message);
    }
}
我遇到的问题让我很困惑

有时我可以成功地将输出文件夹移动到存档,但有时会失败

捕获异常时得到的错误消息是
对路径“Output”的访问被拒绝。

我已检查
输出
文件夹中的所有文件是否未被使用。我不明白为什么访问有时会被拒绝,而不是一直被拒绝

有人能给我解释一下,告诉我如何解决这个问题吗

--编辑--

在HansPassant注释之后,我稍微修改了函数,以获取当前目录并使用完整路径。然而,我仍然有同样的问题

该函数现在如下所示:

static void moveToArchive()
{
    string currentDir = Environment.CurrentDirectory;
    Console.WriteLine("Current Directory = " + currentDir);
    if (!Directory.Exists(currentDir + "\\Archive")) Directory.CreateDirectory(currentDir + "\\Archive");
    string timestamp = DateTime.Now.ToString("yyyyMMddHHmms");
    try
    {
        Directory.Move(currentDir + "\\Output", currentDir + "\\Archive\\" + timestamp);
    }
    catch(Exception e)
    {
        Console.WriteLine("Can not move folder: " + e.Message);
    }
}
我打印出了当前目录,它和我期望的一样,但我仍然无法使用完整路径<代码>对路径“C:\Users\Me\Desktop\FormApp\Output”的访问被拒绝。

--编辑--

谢谢大家的回答和评论

我想你们中的一些人错过了这一部分,所以我要再强调一点

Directory.Move()有时工作,有时失败。

当函数成功时,没有问题<代码>输出文件夹被移动到
存档

当函数失败时,我收到的异常消息是访问路径被拒绝。

请尝试以下操作: 如果这不能解决问题,可以检查/更改防病毒程序,或者其他程序正在锁定某个文件或文件夹

    static object moveLocker = new object();
    static void moveToArchive()
    {
        lock (moveLocker)
        {
            System.Threading.Thread.Sleep(2000);  // Give sometime to ensure all file are closed.

            //Environment.CurrentDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
            string applicationPath = System.AppDomain.CurrentDomain.BaseDirectory;
            string archiveBaseDirectoryPath = System.IO.Path.Combine(applicationPath, "Archive");

            if (!Directory.Exists(archiveBaseDirectoryPath)) Directory.CreateDirectory(archiveBaseDirectoryPath);

            String timestamp = DateTime.Now.ToString("yyyyMMddHHmms");
            String outputDirectory = System.IO.Path.Combine(Environment.CurrentDirectory, "Output");
            String destinationTS = System.IO.Path.Combine(archiveBaseDirectoryPath, timestamp);
            try
            {
                Directory.Move(outputDirectory, destinationTS);                
            }
            catch (Exception ex)
            {
                Console.WriteLine("Can not move folder " + outputDirectory + " to: " + destinationTS + "\n" + ex.Message);
            }
        }
    }

有时,您尝试移动或删除文件或文件夹,并收到访问冲突或文件正在使用错误。要成功删除文件,您需要标识已锁定文件的进程。您需要先退出流程,然后删除特定文件。要知道哪个进程锁定了文件,可以使用本文讨论的方法之一

使用Process Explorer-从下载

Process Explorer显示有关已打开或加载哪些句柄和DLL进程的信息

从Microsoft站点下载Process Explorer并运行该程序。 单击“查找”菜单,然后选择“查找句柄”或“DLL…”。。。 键入文件名(被某个进程锁定的文件名) 键入搜索短语后,单击“搜索”按钮
您应该看到正在访问该文件的应用程序列表

谢谢大家的回复和帮助。我已经弄清了问题所在

这是因为有一个文件没有完全关闭

我正在检查生成的文件,但错过了程序读取的文件

生成的所有文件都已完全关闭。这是一个我用
StreamReader
打开但没有关闭的文件。我修改了代码,现在没有问题了,所以我想这就是问题所在


感谢所有的评论和回答,这肯定能帮助我思考和解决问题。

我最近碰到了同样的问题。使用PE,我认为使用该特定目录的唯一进程是explorer.exe。我用explorer打开了几个窗口,其中一个指向我要移动的那个窗口的父目录

看起来,在我访问了该子文件夹并返回(甚至返回到根级别!)之后,句柄仍然由explorer保留,因此C#无法以任何方式修改它(更改标志、属性等)

为了让C#正常运行,我不得不关闭浏览器窗口

File.SetAttributes(Application.dataPath + "/script", FileAttributes.Normal);
Directory.Move(Application.dataPath + "/script", Application.dataPath + "/../script");

这解决了我的问题。

我也有同样的问题,它有时失败,但不是一直失败。我想我应该将它包装在一个Try-Catch块中,并向用户显示一条拒绝访问的消息,一旦我将它包装在Try-Catch块中,它就停止了失败。我无法解释为什么

 If existingFile.FileName <> newFileName Then
    Dim dir As New IO.DirectoryInfo(existingFile.FilePath)
    Dim path As String = System.IO.Path.GetDirectoryName(dir.FullName)
    newFileName = path & "\" & newFileName

    File.SetAttributes(existingFile.FilePath, FileAttributes.Normal)
        Try
            IO.File.Move(existingFile.FilePath, newFileName)
        Catch ex As Exception

        End Try
End If
如果存在file.FileName newFileName,则
Dim dir作为新IO.DirectoryInfo(existingFile.FilePath)
Dim path作为字符串=System.IO.path.GetDirectoryName(dir.FullName)
newFileName=路径&“\”&newFileName
File.SetAttributes(existingFile.FilePath,FileAttributes.Normal)
尝试
IO.File.Move(existingFile.FilePath,newFileName)
特例
结束尝试
如果结束

确保父文件夹中有“Output”文件夹,并且没有名为“Output”(无文件扩展名)的文件directory@jgauffin输出文件夹确实存在,并且其中没有一个文件名为Output。当moveToArchive()失败时,新生成的输出文件将在Outuput文件夹中创建,覆盖以前运行生成的文件。此代码主要取决于正确设置Environment.CurrentDirectory。这一直都是错误的,它是最糟糕的全局变量。始终使用完整路径名,如c:\foo\bar\baz。永远不要依赖于能够写入c:\program文件,UAC会阻止这种情况。您是否在资源管理器窗口或命令提示窗口中打开了该文件夹?我猜生成文件的代码没有正确关闭它们。它有时可能会工作,因为GC已经收集并最终确定了悬空文件句柄。编写文件的代码可能对本例感兴趣。感谢您的回答。但是,当我复制您的函数时,输出文件夹不是