Streamreader блокирует файл - PullRequest
       10

Streamreader блокирует файл

0 голосов
/ 22 февраля 2012

У меня есть приложение ac # (служба Windows), которое запускает событие таймера, которое читает файлы в каталоге и отправляет SMS с использованием данных в файлах.В следующий раз, когда событие запускается, он пытается переместить обработанные файлы из каталога «Обработано» в каталог «Завершено» перед обработкой новых файлов.Я продолжаю получать исключение «Файл используется другим процессом», хотя я почти уверен, что избавляюсь от всего, что использует файлы.Если я останавливаю службу и запускаю ее снова, файлы освобождаются.Есть идеи?

//Code that fires the timer    
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Timers;

namespace SmsWindowsService
{
    public partial class SmsWindowsService : ServiceBase
    {
        private static System.Timers.Timer aTimer;

        public SmsWindowsService()
        {
            InitializeComponent();

            if (!System.Diagnostics.EventLog.SourceExists("MatterCentreSMSSource"))
            {
                System.Diagnostics.EventLog.CreateEventSource(
                    "MatterCentreSMSSource", "MatterCentreSMSLog");
            }
            elMatterCentreSMS.Source = "MatterCentreSMSSource";
            elMatterCentreSMS.Log = "MatterCentreSMSLog";

        }

        protected override void OnStart(string[] args)
        {
            string logText = string.Empty;

            logText = "MatterCentreSMS Service started successfully on " + DateTime.Now;

            WriteEventLog(logText);

            //Create a timer with a ten second interval.
            aTimer = new System.Timers.Timer(10000);

            //Hook up the Elapsed event for the timer.
            aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

            //Set the Interval to 5 minutes.
            //aTimer.Interval = 300000;
            aTimer.Interval = 60000;
            aTimer.Enabled = true;

            // If the timer is declared in a long-running method, use
            // KeepAlive to prevent garbage collection from occurring
            // before the method ends.
            //GC.KeepAlive(aTimer);
            GC.Collect();
        }

        protected override void OnStop()
        {
            string logText = string.Empty;

            logText = "MatterCentreSMS Service stopped on " + DateTime.Now;

            WriteEventLog(logText);
        }

        private void WriteEventLog(string logText)
        {
            elMatterCentreSMS.WriteEntry(logText);
        }

        private void OnTimedEvent(object source, ElapsedEventArgs e)
        {
            string ex = string.Empty;

            SendSms s = new SendSms();

            ex = s.ProcessSms();

            if (ex.Length > 1)
                WriteEventLog(ex);

            //ex = RestartService("SmsWindowsService", 60000);
            //WriteEventLog(ex);
        }

        public string RestartService(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);

            try
            {
                int millisec1 = Environment.TickCount;
                TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

                service.Stop();
                service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);

                // count the rest of the timeout
                int millisec2 = Environment.TickCount;
                timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds - (millisec2 - millisec1));

                service.Start();
                service.WaitForStatus(ServiceControllerStatus.Running, timeout);

                return "MatterCentreSMS Service successfully restarted on " + DateTime.Now;
            }

            catch (Exception e)
            {
                return Convert.ToString(e);
            }
        }
    }
}

//Code that reads the file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;

namespace SmsWindowsService
{
    class Message
    {
        private string filePath;

        public Message(string filePath)
        {
            this.filePath = filePath;
        }

        public string readSMS(string filePath)
        {
            const string searchmessage = "[B-->]";
            StreamReader smsmessage = new StreamReader(filePath);

            try
            {
                FileInfo filenameinfo = new FileInfo(filePath);
                if (filenameinfo.Exists == false)
                    throw new SMSReaderException(String.Format("SMS Message {0} cannot be found ...", filePath), filePath);

                smsmessage = filenameinfo.OpenText();
                string smsoutput = smsmessage.ReadToEnd();
                int endpos = smsoutput.IndexOf(searchmessage);
                smsoutput = smsoutput.Substring(endpos + searchmessage.Length);
                smsoutput = smsoutput.Replace("&", "&");
                smsoutput = smsoutput.Replace("\"", """);
                smsoutput = smsoutput.Replace("'", "'");

                filenameinfo = null;
                smsmessage.Close();
                smsmessage.Dispose();

                return smsoutput;
            }

            catch(Exception e)
            {
                throw new Exception("Help", e.InnerException);
            }

            finally
            {
                smsmessage.Close();
                smsmessage.Dispose();
            }
        }
    }

    public class SMSReaderException : System.IO.FileNotFoundException
    {
        public SMSReaderException(string message, string filename)
            : base(message, filename)
        {
        }
    }
    }

//Code that connects to web service and send sms
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Net;
using System.Configuration;
using SmsWindowsService.EsendexSendSmsService;

namespace SmsWindowsService
{
    class SendSms
    {
        string filePath = string.Empty;
        string directoryPath = string.Empty;
        string directoryPathProcessing = string.Empty;
        string directoryPathCompleted = string.Empty;
        string smsLogfileDirectory = string.Empty;
        string smsLogfilePath = string.Empty;
        string mattercentreSMS = string.Empty;
        string messageBody = string.Empty;
        string messageId = string.Empty;
        string messageStatus = string.Empty;
        string dateTodayString = string.Empty;
        long mobileNumber;
        EsendexSendSmsService.SendService send;

        public SendSms()
        {
            directoryPath = ConfigurationSettings.AppSettings[@"directoryPath"];
            directoryPathProcessing = ConfigurationSettings.AppSettings[@"directoryPathProcessing"];
            directoryPathCompleted = ConfigurationSettings.AppSettings[@"directoryPathCompleted"];
            smsLogfileDirectory = ConfigurationSettings.AppSettings[@"smsLogfileDirectory"];            
            dateTodayString = DateTime.Now.ToString("yyyy/MM/dd");
            smsLogfilePath = smsLogfileDirectory + dateTodayString.Replace(@"/", "_") + ".txt";
            send = new EsendexSendSmsService.SendService();
        }

        public string ProcessSms()
        {
            string ex = string.Empty;

            try
            {
                DirectoryInfo di = new DirectoryInfo(directoryPathProcessing);

                ex = MoveFilesToCompleted(directoryPathProcessing, directoryPathCompleted);

                if (ex.Length > 1)
                    return ex;

                ex = MoveFilesToProcessing(directoryPath, directoryPathProcessing);

                if (ex.Length > 1)
                    return ex;

                FileInfo[] subFilesProcessing = di.GetFiles();

                foreach (FileInfo subFile in subFilesProcessing)
                {
                    filePath = directoryPathProcessing + subFile.Name;

                    Message sms = new Message(filePath);

                    mattercentreSMS = sms.readSMS(filePath);

                    MessageDetails d = new MessageDetails(mattercentreSMS);

                    mobileNumber = d.GetMobileNumber();
                    messageBody = d.GetMessageBody();

                    ex = SetHeader();

                    if (ex.Length > 1)
                        return ex;

                    ex = SetProxy();

                    if (ex.Length > 1)
                        return ex;

                    //Send the message and get the returned messageID and send status
                    messageId = send.SendMessage(Convert.ToString(mobileNumber), messageBody, EsendexSendSmsService.MessageType.Text);
                    messageStatus = Convert.ToString(send.GetMessageStatus(messageId));

                    ex = WriteLogFile(messageId, subFile.Name, messageStatus);

                    if (ex.Length > 1)
                        return ex;

                    send.Dispose();
                }

                di = null;
                subFilesProcessing = null;

                return ex;
            }

            catch (Exception e)
            {
                return Convert.ToString(e);
            }
        }

        private string MoveFilesToCompleted(string directoryPathProcessing, string directoryPathCompleted)
        {
            DirectoryInfo din = new DirectoryInfo(directoryPathProcessing);

            try
            {                
                FileInfo[] subFiles = din.GetFiles();

                foreach (FileInfo subFile in subFiles)
                {
                    subFile.MoveTo(directoryPathCompleted + subFile.Name);
                }

                subFiles = null;
                return "";                
            }

            catch (Exception e)
            {
                return Convert.ToString(e);
            }

            finally
            {
                din = null;
            }
        }

        private string MoveFilesToProcessing(string directoryPath, string directoryPathProcessing)
        {
            DirectoryInfo din = new DirectoryInfo(directoryPath);

            try
            {
                FileInfo[] subFiles = din.GetFiles();

                foreach (FileInfo subFile in subFiles)
                {
                    subFile.MoveTo(directoryPathProcessing + subFile.Name);
                }

                subFiles = null;
                return "";
            }

            catch (Exception e)
            {
                return Convert.ToString(e);
            }

            finally
            {
                din = null;
            }
        }

        private string SetHeader()
        {
            try
            {
                //Setup account details in the header
                EsendexSendSmsService.MessengerHeader header = new EsendexSendSmsService.MessengerHeader();
                header.Account = ConfigurationSettings.AppSettings[@"smsServiceUrl"];
                header.Username = ConfigurationSettings.AppSettings[@"smsServiceUsername"];
                header.Password = ConfigurationSettings.AppSettings[@"smsServicePassword"];

                // set the SOAP header Authentication values
                send.MessengerHeaderValue = header;

                return "";
            }

            catch (Exception e)
            {
                return Convert.ToString(e);
            }
        }

        private string SetProxy()
        {
            try
            {
                //Create a web proxy object as the proxy server block direct request to esendex 
                WebProxy myProxy = new WebProxy(ConfigurationSettings.AppSettings[@"proxyaddress"], true);
                myProxy.Credentials = new NetworkCredential(ConfigurationSettings.AppSettings[@"username"], ConfigurationSettings.AppSettings[@"password"]);
                WebRequest.DefaultWebProxy = myProxy;
                send.Proxy = myProxy;

                return "";
            }

            catch (Exception e)
            {
                return Convert.ToString(e);
            }
        }

        private string WriteLogFile(string messageId, string smsFileName, string messageStatus)
        {
            try
            {
                if (File.Exists(smsLogfilePath))
                {
                    //file is not empty - append log entry to file
                    using (StreamWriter writeSmsLog = File.AppendText(smsLogfilePath))
                    {
                        writeSmsLog.WriteLine(messageId + "             " + smsFileName + "    " + DateTime.Now + "     " + messageStatus);
                        writeSmsLog.Close();
                    }
                }
                else
                {
                    FileStream fs = File.OpenWrite(smsLogfilePath);
                    fs.Flush();
                    fs.Close();
                    fs.Dispose();

                    using (StreamWriter writeSmsLog = new StreamWriter(smsLogfilePath, true))
                    {
                        writeSmsLog.WriteLine("Message_ID                                       File_Name                                    Date_Sent                  Status");
                        writeSmsLog.WriteLine("======================================================================================================================================");
                        writeSmsLog.WriteLine(messageId + "             " + smsFileName + "    " + DateTime.Now + "     " + messageStatus);
                        writeSmsLog.Close();
                    }
                }

                return "";
            }

            catch (Exception e)
            {
                return Convert.ToString(e);
            }
        }
    }
}

Ответы [ 2 ]

7 голосов
/ 22 февраля 2012

Есть идеи?

Вы запускаете средство проверки на вирусы в совершенно другом процессе. Он обнаруживает, что файл изменился, и на мгновение блокирует его, чтобы проверить, не представляет ли вирус, который вы только что выполнили, файл. Это разблокирует его через пару миллисекунд.

Отключение проверки на вирусы - плохая идея. Вместо этого вам просто придется жить с этим; напишите свой код, чтобы быть надежным в мире, где существует множество процессов, борющихся за блокировки файлов.

1 голос
/ 24 февраля 2012
StreamReader smsmessage = new StreamReader(filePath);

try
{
    FileInfo filenameinfo = new FileInfo(filePath);
    ....
    smsmessage = filenameinfo.OpenText();
    ...

Вы инициализируете smsmessage дважды, но удаляете только один из этих экземпляров. Первая строка создает StreamReader, а затем вы перезаписываете свою ссылку на этот экземпляр на экземпляр, созданный filenameinfo.OpenText (). Это оставляет вас с экземпляром, который больше не имеет никаких ссылок и не был удален. Этот экземпляр может содержать блокировку файла, и у вас нет никаких гарантий относительно того, когда он будет удален. Даже если он не удерживает блокировку, вы все равно должны это исправить.

...