我正在使用C#在Visual Studio 2010中编写此Windows Form应用程序。
表单上有一个执行按钮,用户将点击按钮,程序将生成一些文件并存储在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:UsersMeDesktopFormAppOutput' is denied.
--编辑--
谢谢大家的回答和评论。
我想你们中的一些人错过了这部分,所以我要强调它。
Directory.Move() 有时工作,有时失败。
当函数成功时,没有问题。 Output
文件夹将移动到Archive
当函数失败时,我收到的异常消息是访问路径被拒绝。
谢谢大家的回复和帮助。我已经弄清楚了问题所在。
这是因为有一个文件没有完全关闭。
我正在检查生成的文件,并错过了程序正在读取的文件。
生成的所有文件均已完全关闭。这是我用来打开StreamReader
但没有关闭的一个文件。我修改了代码,现在没有问题,所以我认为这就是问题所在。
感谢您的所有评论和回答,这绝对有助于我思考和解决问题。
请参阅 http://windowsxp.mvps.org/processlock.htm
有时,您尝试移动或删除文件或文件夹,并收到访问冲突或文件正在使用 - 错误。要成功删除文件,您需要确定锁定文件的进程。您需要先退出进程,然后删除特定文件。要知道哪个进程锁定了文件,您可以使用本文中讨论的方法之一。
使用进程资源管理器 - 从 http://download.sysinternals.com/files/ProcessExplorer.zip 下载
进程资源管理器显示有关已打开或加载的进程句柄和 DLL 的信息。
从Microsoft站点下载进程资源管理器并运行该程序。单击"查找"菜单,然后选择"查找句柄"或"DLL..."。键入文件名(被某个进程锁定的文件的名称。键入搜索短语后,点按"搜索"按钮您应该会看到正在访问该文件的应用程序列表。
我最近遇到了同样的问题。使用 PE,我认为使用该特定目录的唯一进程是资源管理器.exe。我用资源管理器打开了几个窗口,其中一个指向我将要移动的一个父目录。
看起来,在我访问该子文件夹然后返回(甚至到根级别!)句柄仍然由资源管理器保留,因此 C# 无法以任何方式修改它(更改标志、属性等)。
我不得不杀死该资源管理器窗口才能使 C# 正常运行。
File.SetAttributes(Application.dataPath + "/script", FileAttributes.Normal);
Directory.Move(Application.dataPath + "/script", Application.dataPath + "/../script");
这解决了我的问题。
试试这个:如果这不能解决,请检查/更改防病毒软件,或者其他程序正在锁定某些文件或文件夹。
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);
}
}
}
我遇到了同样的问题,它有时会失败,但并非一直失败。我以为我会将其包装在 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);
}
}