2

I'm new to C# and have been asked to write a custom task in a plugin for our deployment software, but I just can't wrap my head around this. I'm simply trying to log some data that is in a certain directory on my deployment server to the output log, but I only get the first file logged (and then even the text is garbled, I think it's loading the bytes wrong somehow) before getting strange errors about "Additional information: Collection was modified; enumeration operation may not execute."

Here is the code I have so far:

class Clense : AgentBasedActionBase
{
    public string dataPath { get; set; }

    protected override void Execute()
    {
        IFileOperationsExecuter agent = Context.Agent.GetService<IFileOperationsExecuter>();
        GetDirectoryEntryCommand get = new GetDirectoryEntryCommand() { Path = dataPath };
        GetDirectoryEntryResult result = agent.GetDirectoryEntry(get);
        DirectoryEntryInfo info = result.Entry;
        // info has directory information
        List<FileEntryInfo> myFiles = info.Files.ToList();
        foreach (FileEntryInfo file in myFiles)
        {
            Byte[] bytes = agent.ReadFileBytes(file.Path);
            String s = Encoding.Unicode.GetString(bytes);
            LogInformation(s);
            // myFiles.Remove(file); 
        }
    }
}

Does anyone know what I can do to try to fix this?

Update

Removing the myFiles.Remove() fixed the error (I thought it would loop too many times but it doesn't) and it looks like I'm getting one log entry per file now, but the messages are still garbled. Does anyone have any idea why this is happening?

java_joe
  • 21
  • 2

3 Answers3

1

You can either iterate the myFiles collection in the reverse direction (so that you don't corrupt the collection when you remove each individual file), or you can simply clear the collection when you are done iterating it (which would accomplish the same thing).

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
1

You are modifying the collection with myFiles.Remove(file); Delete that line (since it's the cause).

SingleStepper
  • 348
  • 1
  • 10
0

In his comment, Blorgbeard is almost certainly correct with regards to the encoding used to read the files on disk. Remember that Encoding.Unicode is actually UTF16, which is somewhat confusing, and if I had to guess, probably not the encoding your files were created with.

For completeness, I will add the BuildMaster-idiomatic way to handle your scenario using the ReadAllText() extension method on IFileOperationsExecuter:

protected override void Execute()
{
    var agent = this.Context.Agent.GetService<IFileOperationsExecuter>();
    var entry = agent.GetDirectoryEntry(new GetDirectoryEntryCommand() { Path = dataPath }).Entry;
    foreach(var file in entry.Files) 
    {
        string contents = agent.ReadAllText(file.Path);
        this.LogInformation(contents);
    }
}

The ReadAllText() method will internally assume UTF8 encoding, but there is an overload that accepts a different encoding if necessary.

John Rasch
  • 62,489
  • 19
  • 106
  • 139