Windows Server 2012 System.IndexOutOfRangeExceptio

Windows Server 2012 System.IndexOutOfRangeException
2021-09-15
  •  译文(汉语)
  •  原文(英语)

我已经编写了一项服务,并且在我的计算机上也能正常工作,但是当我将其移至应该在其上运行的服务器上时,无论何时它也应该像其应有的那样读写文件,都会吐出System.IndexOutOfRangeException.我只是觉得很奇怪,它仅在服务器上执行此操作,而且我不知道它们与我的计算机的工作方式不同,因此将不胜感激.

说明:由于未处理的异常,进程已终止.异常信息:System.IndexOutOfRangeException堆栈:在emlService.emlService.runProc()在System.Threading.ThreadHelper.ThreadStart_Context(System.Object)在System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext,System.Threading.ContextCallback, System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,System.Threading.ContextCallback,System.Object,Boolean)在System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,System. System.Threading.ThreadHelper.ThreadStart()上的Threading.ContextCallback,System.Object)

代码

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;
            }
        }
    }
}
解决过程1

据我所知,您并没有检查linestring任何地方的长度.我不能肯定地说,因为您没有提供足够的信息,但是我linestring.Length少于17人,因此引发parserObject.DecodeFrom64(linestring[17]);了异常.可能linestring.Length小于12,也就是之前的那一行.

要解决此问题,您应检查的长度linestring并适当处理结果.

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

与您的问题无关,但我对您的影响感到好奇lines.Select(c => c.ToString().File.ReadAllLines()已经返回了一个字符串数组,所以`Select(c => c.ToString())是多余的.

速聊1:
我用另一种方式解决了这个问题,但是我一定会将此代码添加到我的服务中,谢谢!至于ReadAllLines,我还不知道它是这样工作的,我刚刚终于使该服务开始工作,并且将在接下来的几天内对其进行优化,我肯定会在这里进行更改,谢谢!
解决过程2

在您正在阅读的一行中,线串不是您期望的长度.

您确定这将永远不会失败吗?

linestring[17]

如果文件中有空行怎么办?

速聊1:
啊,谢谢,这促使我查看了文件,但它们实际上已损坏,谢谢!

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;
            }
        }
    }
}
Solutions1

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.

Talk1:
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!
Solutions2

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?

Talk1:
Ah thanks, this prompted me to look at the files, and they were actually corrupt, thanks!
转载于:https://stackoverflow.com/questions/15559981/windows-server-2012-system-indexoutofrangeexception

本人是.net程序员,因为英语不行,使用工具翻译,希望对有需要的人有所帮助
如果本文质量不好,还请谅解,毕竟这些操作还是比较费时的,英语较好的可以看原文

留言回复
我们只提供高质量资源,素材,源码,坚持 下了就能用 原则,让客户花了钱觉得值
上班时间 : 周一至周五9:00-17:30 期待您的加入