0

I have wrote a service and it works just fine on my computer but when I move it onto the server it is supposed to run on, it is spitting out System.IndexOutOfRangeException whenever it goes to read/write the file like its supposed too. I just find it weird that it is doing this only on the server, and I dont know how they work differently to my computer so any help would be appreciated.

Description: The process was terminated due to an unhandled exception. Exception Info: System.IndexOutOfRangeException Stack: at emlService.emlService.runProc() at System.Threading.ThreadHelper.ThreadStart_Context(System.Object) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) at System.Threading.ThreadHelper.ThreadStart()

The code

public partial class emlService : ServiceBase
{
    Boolean _isRunning;

    public emlService()
    {
        InitializeComponent();
        if (!System.Diagnostics.EventLog.SourceExists("emlServiceSource"))
        {
            System.Diagnostics.EventLog.CreateEventSource(
                "emlServiceSource", "emlServiceLog");
        }
        eventLog1.Source = "emlSerivceSource";
        eventLog1.Log = "emlServiceLog";
    }

    protected override void OnStart(string[] args)
    {
        eventLog1.WriteEntry("In OnStart");
        Thread NewThread = new Thread(new ThreadStart(runProc));
        _isRunning = true;
        //Creates bool to start thread loop
        if (_isRunning)
        {
            NewThread.Start();
        }
    }

    protected override void OnStop()
    {
        eventLog1.WriteEntry("In OnStop");
        _isRunning = false;             
    }

    protected override void OnContinue()
    {            
    }

    public void runProc()
    {         

        //Directory of the drop location
        string tempDrop = ConfigurationSettings.AppSettings["conf_drop"];
        DirectoryInfo drop = new DirectoryInfo(tempDrop);

        //Directory of the pickup location
        string tempPickup = ConfigurationSettings.AppSettings["conf_pickup"];
        string destpath = tempPickup;

        //Inits ParserCommands and DropDirectory object
        ParserCommands parserObject = new ParserCommands();

        //Inits array to hold number of messages in drop location
        FileInfo[] listfiles;

        //Inits CFG
        string conf_mailsender = ConfigurationSettings.AppSettings["conf_mailsender"];
        string conf_rcpt = ConfigurationSettings.AppSettings["conf_rcpt"];
        string conf_username_and_password = ConfigurationSettings.AppSettings["conf_username_and_password"];
        string conf_sender = ConfigurationSettings.AppSettings["conf_sender"];
        string conf_raport = ConfigurationSettings.AppSettings["conf_raport"];

        //Loop that never ends
        while (true) 
        {
            //Reduces load on machine
            Thread.Sleep(1000);

            //Checks if there is a message waiting to be processed and begins processing if so
            listfiles = drop.GetFiles();
            if (listfiles.Length >= 1)
            {
                for (int j = 0; j <= (listfiles.Length - 1); j++)
                {
                    //Gives it time to breathe
                    Thread.Sleep(250);

                    try
                    {
                        //Gets each line of the original .eml into a string array
                        var lines = File.ReadAllLines(listfiles[j].FullName);
                        string[] linestring = lines.Select(c => c.ToString()).ToArray();

                        //Seperates start of email from the rest and decode parameter_content
                        string parameter_to = parserObject.getReciever(linestring[12]);
                        string parameter_content = parserObject.DecodeFrom64(linestring[17]);

                        //Creates string ready for base64 encode
                        string encode = "from=" + conf_sender + "&to=" + parameter_to + "&raport=" + conf_raport + "&message=" + parameter_content;

                        //Opens up steam and writer in the new dest, creates new .eml file
                        using (FileStream fs = new FileStream(destpath + listfiles[j].Name, FileMode.CreateNew))
                        using (StreamWriter writer = new StreamWriter(fs))
                        {

                            //Writes all .eml content into buffer
                            writer.WriteLine("x-sender: " + conf_mailsender);
                            writer.WriteLine("x-receiver: " + conf_rcpt);
                            writer.WriteLine(linestring[2]);
                            writer.WriteLine(linestring[3]);
                            writer.WriteLine(linestring[4]);
                            writer.WriteLine(linestring[5]);
                            writer.WriteLine(linestring[6]);
                            writer.WriteLine(linestring[7]);
                            writer.WriteLine(linestring[8]);
                            writer.WriteLine("From: " + conf_mailsender);
                            writer.WriteLine(linestring[10]);
                            writer.WriteLine("Reply-To: " + conf_mailsender);
                            writer.WriteLine("To: " + conf_rcpt);
                            writer.WriteLine("Subject: " + conf_username_and_password);
                            writer.WriteLine("Return-Path: " + conf_mailsender);
                            writer.WriteLine(linestring[15]);
                            writer.WriteLine();

                            //Writes encoded string into buffer
                            writer.WriteLine(parserObject.EncodeTo64(encode));

                            //Writes buffer into .eml file
                            writer.Flush();
                        }

                        lines = null;
                    }
                        catch (System.IO.IOException e)
                    {
                        Console.WriteLine("no");

                    }

                    //Deletes the file
                    File.Delete(listfiles[j].FullName);
                }

                //Sets the number of files needing sent to 0
                listfiles = null;
            }
        }
    }
}
user345453
  • 52
  • 1
  • 10

2 Answers2

3

As far as I can tell, you aren't checking the length of linestring anywhere. I can't say for sure since you haven't provided enough information, but I would be that linestring.Length is less than 17, causing parserObject.DecodeFrom64(linestring[17]); to throw the exception. It could just as well be that linestring.Length is less than 12, and it's the line before that.

To fix this, you should check the length of linestring and handle the result appropriately.

string[] linestring = lines.Select(c => c.ToString()).ToArray();
if(linestring.Length <= 17)
{
    //handle malformed file
}
else
{
    //complete the processing
}

Unrelated to your question, but I'm curious as to what you think the effect of lines.Select(c => c.ToString() is. File.ReadAllLines() already returns a string array, so the `Select(c => c.ToString()) is redundant.

Jason Watkins
  • 3,766
  • 1
  • 25
  • 39
  • I fixed this another way, but I will definitely add this code into my service, thanks! As for the ReadAllLines, I was not aware it worked this way, I have just finally got the service working and am going to optimise it over the next couple of days, I will definitely make the change there, thanks! – user345453 Mar 22 '13 at 00:06
2

On one of your lines you're reading, linestring is not the length you expect it to be.

Are you sure this will never fail?

linestring[17]

What if your file has an empty line in it?

rein
  • 32,967
  • 23
  • 82
  • 106