[英].NET Directory.Move results in Access to path is denied with network paths
[英]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.