C# 无法以编程方式覆盖IIS虚拟目录/应用程序中的文件(文件始终处于锁定状态)
起初我以为我面临的是一项非常简单的任务。但现在我意识到这并不像我想象的那样有效,所以现在我希望你们能帮助我,因为我现在几乎陷入困境 我的场景如下(在Windows 2008 R2服务器上):C# 无法以编程方式覆盖IIS虚拟目录/应用程序中的文件(文件始终处于锁定状态),c#,iis,file-locking,C#,Iis,File Locking,起初我以为我面临的是一项非常简单的任务。但现在我意识到这并不像我想象的那样有效,所以现在我希望你们能帮助我,因为我现在几乎陷入困境 我的场景如下(在Windows 2008 R2服务器上): 一个文件每天上传3次到FTP目录。文件名始终相同,这意味着每次都会覆盖现有文件 我已经编写了一个简单的C#服务,用于监视FTP上传目录,为此我使用FileSystemWatcher类 上传文件需要几分钟的时间,所以一旦文件观察者注册了更改,我会定期尝试打开文件,查看文件是否仍在上传(或锁定) 一旦文件不再被
private bool FileReadable(string file, int timeOutSeconds)
{
DateTime timeOut = DateTime.Now.AddSeconds(timeOutSeconds);
while (DateTime.Now < timeOut)
{
try
{
if (File.Exists(file))
{
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None))
{
return true;
}
}
return false;
}
catch (Exception)
{
Thread.Sleep(500);
}
}
m_log.LogLogic(0, "FileReadable", "Timeout after [{0}] seconds trying to open the file {1}", timeOutSeconds, file);
return false;
}
EDIT2:
在客户端下载文件时终止w3wp.exe进程对我们来说没有问题。我只是很难找到正确的w3wp.exe进程来锁定文件
另外,我的客户端应用程序正在客户端上下载文件,它正在检查HTTP头的最后修改日期。客户每10分钟检查一次日期。因此,该文件可能被IIS锁定,因为有客户端在不断地检查HTTP头以查找该文件。尽管如此,我不明白为什么我可以通过windows资源管理器手动删除/重命名/移动文件而不会出现任何问题。为什么会这样,为什么我的应用程序会出现“被另一个进程锁定”异常?我遇到的一个问题是,文件在编写过程中仍然存在,这意味着它也会被锁定。如果此时调用了FileReadable()函数,它将返回false
我的解决方案是,在写入文件的过程中,将文件写入(比如)OUTPUT1.TXT,然后在完全写入并关闭文件流后,将其重命名为OUTPUT2.TXT。这样,OUTPUT2.TXT的存在表示该文件已被写入并(希望)解锁。只需在FileReadable()循环中检查OUTPUT2.TXT 您正在对问题的症状进行故障排除,而不是对根本原因进行修复。如果你想沿着这条路走下去,这里是终止进程的代码——但更好的办法是正确地完成它并找出错误所在。我建议在FileReadable的Catch异常中:
catch (Exception ex) {
if (ex is IOException && IsFileLocked(ex)) {
//Confirm the code see's it as a FileLocked issue, not some other exception
//its not safe to unlock files used by other processes, because the other process is likely reading/writing it.
}
}
private static bool IsFileLocked(Exception exception)
{
int errorCode = Marshal.GetHRForException(exception) & ((1 << 16) - 1);
return errorCode == 32 || errorCode == 33;
}
catch(异常示例){
if(ex是IOException&&IsFileLocked(ex)){
//确认代码将其视为文件锁定问题,而不是其他异常
//解锁其他进程使用的文件不安全,因为其他进程可能正在读取/写入它。
}
}
私有静态bool IsFileLocked(异常)
{
int errorCode=Marshal.GetHRForException(异常)和((1在您的示例代码中,我看不到您正在关闭文件流的位置。保持文件流打开将保持对文件的锁定。关闭流是一个好主意。您可能不想杀死w3wp.exe进程,正如其他人所提到的那样。大家都说
“做得更好”
没人说怎么办!!!
这就是方法。因为你提到了“我的客户端应用程序”,这里有一个关键的机会,如果你不能控制读取文件的应用程序,你就不会有这个机会
每次只需使用新的文件名。
您可以控制程序读取和写入文件。在文件名中添加一个递增的#,让客户端选择最大的#(实际上是最晚的日期,然后您的数字可以环绕)。如果可以,让writer程序清理旧文件;如果不清理,则不会造成任何伤害。IIS最终会放弃这些文件。如果不清理,请每周打开资源管理器,自己动手
其他关键是更新频率低(无法生成文件)
catch (Exception ex) {
if (ex is IOException && IsFileLocked(ex)) {
//Confirm the code see's it as a FileLocked issue, not some other exception
//its not safe to unlock files used by other processes, because the other process is likely reading/writing it.
}
}
private static bool IsFileLocked(Exception exception)
{
int errorCode = Marshal.GetHRForException(exception) & ((1 << 16) - 1);
return errorCode == 32 || errorCode == 33;
}