ผมเคยเจอปัญหา System.UnauthorizedAccessException: Access to the path 'D:\wwwroot\***\***' is denied.
เนื่องจาก ขณะที่กำลังอ่าน xml อยู่นั้น ไฟล์มันยังถูกเขียนไม่เสร็จ เมื่อเราพยายามอ่านไฟล์ดังกล่าว จึงเจอ access is denied. ผมเจอ code ที่เเก้ปัญหานั้นได้เเล้ว
คือ windows service ที่ผมเขียนไว้จะคอยดักจับว่าโฟล์เดอร์นี้มี filechage ก็เริ่มเเกะ xml ทันที เเต่เราเพิ่มไปอีกนิืดว่า จะรอให้ ftp มันเขียนไฟล์เสร็จก่อน เราจึงเริ่มเเกะ xml ได้ โดยวน loop ดู 10 ครั้งจนกว่าจะ access ไฟล์ได้ เเต่ละ loop เมื่อติด exception ว่ายัง access denied ให้ sleep 500 มิลลิวินาที เเล้วไปยัง loop ครั้งถัดไป จนกว่าจะ access ไฟล์ได้
โค้ด: เลือกทั้งหมด
bool WaitForFile(string fullPath, string fileName)
{
string strfileName = string.Empty;
int numTries = 0;
while (true)
{
++numTries;
try
{
// Attempt to open the file exclusively.
using (FileStream fs = new FileStream(fullPath,
FileMode.Open, FileAccess.ReadWrite,
FileShare.None, 100))
{
fs.ReadByte();
// If we got this far the file is ready
string destFileName = XmlLogPath;
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
string dd = DateTime.Now.ToString("yyyy-MM-dd");
destFileName = destFileName + @"\" + dd;
if (!Directory.Exists(destFileName))
{
Directory.CreateDirectory(destFileName);
}
strfileName = fileName;
strfileName = strfileName + "_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss-fff") + ".xml";
destFileName = destFileName + @"\" + strfileName;
if (!File.Exists(destFileName))
{
FileStream fs2 = new FileStream(destFileName, FileMode.Append);
StreamWriter writer = new StreamWriter(fs2, System.Text.Encoding.GetEncoding(874));
try
{
byte[] b = new byte[1024];
UTF8Encoding temp = new UTF8Encoding(true);
while (fs.Read(b, 0, b.Length) > 0)
{
writer.Write(temp.GetString(b));
}
}
catch (Exception ex)
{
log.Error(ex.Message.ToString());
}
finally
{
writer.Close();
fs.Close();
fs2.Close();
}
}
break;
}
}
catch (Exception ex)
{
log.Info(string.Format("WaitForFile {0} failed to get an exclusive lock: {1}",fullPath, ex.ToString()));
if (numTries > 10)
{
log.Info(string.Format("WaitForFile {0} giving up after 10 tries",fullPath));
return false;
}
// Wait for the lock to be released
System.Threading.Thread.Sleep(500);
}
}
log.Info(string.Format("WaitForFile {0} returning true after {1} tries",fullPath, numTries));
return true;
}