簡體   English   中英

Directory.Move():拒絕訪問路徑

[英]Directory.Move(): Access to Path is Denied

我正在使用 C# 在 Visual Studio 2010 中編寫此 Windows 窗體應用程序。

表單上有一個 Execute 按鈕,用戶點擊按鈕,程序會生成一些文件並存儲在Output文件夾中(由程序使用Directory.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);
    }
}

我遇到的問題讓我很困惑......

有時我可以成功地將輸出文件夾移動到存檔,但有時會失敗。

我從捕獲異常中得到的錯誤消息是Access to path 'Output' is denied.

我已經檢查過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);
    }
}

我打印了當前目錄,它正如我所期望的那樣,但我仍然無法使用完整路徑。 Access to path 'C:\\Users\\Me\\Desktop\\FormApp\\Output' is denied.

- 編輯 -

謝謝大家的回答和評論。

我想你們中的一些人會錯過這部分,所以我要再強調一點。

Directory.Move() 有時工作,有時失敗。

當函數成功時,沒有問題。 Output文件夾移動到Archive

當函數失敗時,我得到的異常消息是訪問路徑被拒絕。

謝謝大家的回復和幫助。 我已經弄清楚是什么問題了。

這是因為有一個文件沒有完全關閉。

我正在檢查生成的文件,但錯過了程序正在讀取的文件。

生成的所有文件都已完全關閉。 這是我使用StreamReader打開但沒有關閉的一個文件。 我修改了代碼,現在沒有問題,所以我認為這就是問題所在。

感謝所有的評論和答案,這絕對可以幫助我思考和解決問題。

請參閱http://windowsxp.mvps.org/processlock.htm

有時,您嘗試移動或刪除文件或文件夾並收到訪問沖突或文件正在使用 - 錯誤。 要成功刪除文件,您需要確定鎖定文件的進程。 您需要先退出進程,然后刪除特定文件。 要知道哪個進程鎖定了文件,您可以使用本文中討論的方法之一。

使用 Process Explorer - 從http://download.sysinternals.com/files/ProcessExplorer.zip下載

進程資源管理器向您顯示有關哪些句柄和 DLL 進程已打開或加載的信息。

從 Microsoft 站點下載 Process Explorer 並運行該程序。 單擊查找菜單,然后選擇查找句柄或 DLL... 輸入文件名(被某些進程鎖定的文件的名稱。) 輸入搜索短語后,單擊搜索按鈕 您應該會看到應用程序列表訪問文件。

我最近遇到了同樣的問題。 使用 PE 我認為只有使用該特定目錄的進程是 explorer.exe。 我用資源管理器打開了幾個窗口,一個指向我將要移動的一個的父目錄。

看來,在我訪問該子文件夾然后返回(甚至到根級別!)后,句柄仍由資源管理器保留,因此 C# 無法以任何方式修改它(更改標志、屬性等)。

為了讓 C# 正常運行,我不得不關閉那個資源管理器窗口。

試試這個:如果這不能解決,也許檢查/更改防病毒軟件,或者其他程序正在鎖定某個文件或文件夾。

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

我有一個類似的問題。 遵循特定模板時,在循環中重命名許多目錄。 程序有時會在不同的目錄上崩潰。 它有助於在 Directory.Move 之前添加睡眠線程 我需要制造一些延遲。 但它減慢了復制過程。

foreach (var currentFullDirPath in Directory.GetDirectories(startTargetFullDirectory, "*", SearchOption.AllDirectories))
            {
                var shortCurrentFolderName = new DirectoryInfo(currentFullDirPath).Name.ToLower();
                if (shortCurrentFolderName.Contains(shortSourceDirectoryName))
                {
                    // Add Thread.Sleep(1000);
                    Thread.Sleep(1000);
                    var newFullDirName = ...;
                    Directory.Move(currentFullDirPath, newFullDirName);
                }
            }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM