SdFat: How to reset openNext?

Dear all,
I am trying to write an App that allows me to download data logged on an SD-card via the microcontroller, in my case, a Mega (selfmade clone with a FT321 for serial comm, passed all tests I made, propably works fine). Arduino IDE i 1.8.5, app will be a windows form in c#, written in Visual Studio 2013. Since I never progammed in c#, I just picked together what I needed on youtube and tutorials; still lots to be done.
In data transfer mode, the sketch uses first a file.openNext routine to count the files available, and then I want to use it again to go through the root directory file by file, first sending the filename to the host computer, then sending the content of the file with a modification of the getline example. Finally, I rename the file so that it ends up in an “old”-folder:

#include <BlockDriver.h>
#include <MinimumSerial.h>
#include <SdFat.h>
#include <SdFatConfig.h>
#include <SysCall.h>


// SD chip select pin
const uint8_t chipSelect = SS;

// file system object
SdFat sd;

SdFile file;

char Dateiname[13];
char NewFileName[17];
unsigned int nameLen;

// create a serial stream
ArduinoOutStream cout(Serial);

int cmd;

const int data_line_length = 256;
char data_line[data_line_length];
unsigned int file_count = 0;

//------------------------------------------------------------------------------
void setup() {
  Serial.begin(115200);
  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
}
//------------------------------------------------------------------------------
void loop() {
  while (!Serial.available()) {}  // wait for Leonardo

  cmd = Serial.read();
  if (cmd == 99) //c for count
  {
    // open next file in root.  The volume working directory, vwd, is root
    while (file.openNext(sd.vwd(), O_READ))
    {
      if (file.isFile())
      {
        file_count++;
        Serial.print("+");
      }
      file.close();
    }
    Serial.println(file_count);
    file_count = 0;
    sd.vwd()->rewind();
  }

  else if (cmd == 110) //n for name
  {
    Serial.println("n received");
    do {
      file.openNext(sd.vwd(), O_READ);
      Serial.println("do loop");
    } while (!file.isFile());

    file.getName(Dateiname, &nameLen);
    Serial.println(Dateiname);
  }

  else if (cmd == 115) //s for send
  {
    send_all_lines();

    MakeNewFilename(NewFileName);
    file.rename(sd.vwd(), NewFileName); //do the rename, or rather not
    file.close();
  }
}

void send_all_lines() {
  const int data_line_length = 256;
  char data_line[data_line_length];
  ifstream sdin(Dateiname);

  while (sdin.getline(data_line, data_line_length, '\n') || sdin.gcount()) {
    int count = sdin.gcount();
    if (sdin.fail()) {
      cout << "Partial long line";
      sdin.clear(sdin.rdstate() & ~ios_base::failbit);
    } else if (sdin.eof()) {
      cout << "Partial final line";  // sdin.fail() is false
    } else {
      count--;  // Don’t include newline in count
    }
    //cout << " (" << count << " chars): " << data_line << endl;
    cout << data_line << endl;
  }
}

void MakeNewFilename(char *NewFileName)
{
  NewFileName[0] = 'o';
  NewFileName[1] = 'l';
  NewFileName[2] = 'd';
  NewFileName[3] = '/';
  NewFileName[4] = Dateiname[0];
  NewFileName[5] = Dateiname[1];
  NewFileName[6] = Dateiname[2];
  NewFileName[7] = Dateiname[3];
  NewFileName[8] = Dateiname[4];
  NewFileName[9] = Dateiname[5];
  NewFileName[10] = Dateiname[6];
  NewFileName[11] = Dateiname[7];
  NewFileName[12] = Dateiname[8];
  NewFileName[13] = Dateiname[9];
  NewFileName[14] = Dateiname[10];
  NewFileName[15] = Dateiname[11];
  NewFileName[16] = Dateiname[12];
  return;
}

But it doesn’t work. On a hunch, I took the original openNext example and modified it like this:

/*
   Print size, modify date/time, and name for all files in root.
*/
#include <SdFat.h>

// SD chip select pin
const uint8_t chipSelect = SS;

// file system object
SdFat sd;

SdFile file;
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  while (!Serial) {} // wait for Leonardo
  delay(1000);

  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();

  // open next file in root.  The volume working directory, vwd, is root
  while (file.openNext(sd.vwd(), O_READ)) {
    file.printFileSize(&Serial);
    Serial.write(' ');
    file.printModifyDateTime(&Serial);
    Serial.write(' ');
    file.printName(&Serial);
    if (file.isDir()) {
      // Indicate a directory.
      Serial.write('/');
    }
    Serial.println();
    file.close();
  }
  Serial.println("Done!");
}
//------------------------------------------------------------------------------
void loop() {
  // open next file in root.  The volume working directory, vwd, is root
  while (file.openNext(sd.vwd(), O_READ)) {
    file.printFileSize(&Serial);
    Serial.write(' ');
    file.printModifyDateTime(&Serial);
    Serial.write(' ');
    file.printName(&Serial);
    if (file.isDir()) {
      // Indicate a directory.
      Serial.write('/');
    }
    Serial.println();
    file.close();
  }
  Serial.println("Done!");
  delay(5000);
}

That gives me one correct report of the contents of the SD-card, an immediate second “Done!”, and the another “Done!” every five seconds.
Is there a way to reset the openNext function? I want to count files first in order to make my app go through a loop the right amount of times, downloading one file at a time. But maybe that is not even the best way.
Thanks for any hints.
CHeers
Sebastian

Oh no… I found sd.vwd()->rewind();
Sorry, but I did not find that all weekend…
Anyways, I updated the code above, since I have now a problem geting the filenames one by one. I get stuck within the do-loop.
Any thoughts?

Hello again,
the good news is, it works now together with the serial monitor. I know, it is a little weird to open a post and then solve it, but I tried the entire weekend to no avail and now it just came all together.
I made the following adjustments:

void loop() {
  while (!Serial.available()) {}

  cmd = Serial.read();
  if (cmd == 99) //c for count
  {
    // open next file in root.  The volume working directory, vwd, is root
    while (file.openNext(sd.vwd(), O_READ))
    {
      if (file.isFile())
      {
        file_count++;
        //Serial.print("+");
      }
      file.close();
    }
    Serial.println(file_count);
    file_count = 0;
    sd.vwd()->rewind();
  }

  else if (cmd == 110) //n for name
  {
    do {
      file.openNext(sd.vwd(), O_READ);

      if (file.isDir())
      {
        file_flag = false;
        file.close();
      }
      else
      {
        file_flag = true;
      }
    } while (file_flag == false);

    file.getName(Dateiname, &nameLen);
    Serial.println(Dateiname);
    file.close();
  }

  else if (cmd == 115) //s for send
  {
    send_all_lines();
    file.open(Dateiname);
    MakeNewFilename(NewFileName);
    Serial.println(NewFileName);
    file.rename(sd.vwd(), NewFileName);
    file.close();
  }
}

However, now comes the really hard part. As mentioned before, I never learned how to code in c#, and hence do not have the theoretical foundations. What I have until now is this (for which thanks are due to Chatchai Buekban, educ8s.tv, and TheTechDesk):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;

namespace FileDownloader02
    {
    public partial class Form1 : Form
        {

        private SerialPort myport;
        private string in_data;
        private string filename;
        private Int16 file_number;
        private string path;
        String[] ports;
        UInt16 i;

        public Form1()
            {
            InitializeComponent();
            getAvailableComPorts(); 

                    foreach (string myport in ports)
                {
                comboBox1.Items.Add(myport);
                Console.WriteLine(myport);
                if (ports[0] != null)
                    {
                    comboBox1.SelectedItem = ports[0];
                    }

                }
                    btn_dwnload.Enabled = false;
                    btn_disconnect.Enabled = false;
                    btn_count_files.Enabled = false;
            }

        private void getAvailableComPorts()
            {
            ports = SerialPort.GetPortNames();
            }

        private void Form1_Load(object sender, EventArgs e)
            {

            }


        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
            {

            }

        private void btn_connect_MouseClick(object sender, MouseEventArgs e)
            {
            myport = new SerialPort();
            string selectedPort = comboBox1.GetItemText(comboBox1.SelectedItem);
            myport.BaudRate = Convert.ToInt32(tb_baud_rate.Text);
            myport.PortName = selectedPort;
            myport.Parity = Parity.None;
            myport.DataBits = 8;
            myport.StopBits = StopBits.One;

            try
                {
                myport.Open();
                }
            catch (Exception ex)
                {
                MessageBox.Show(ex.Message, "Wrong Port");
                }
            btn_dwnload.Enabled = true;
            btn_disconnect.Enabled = true;
            btn_count_files.Enabled = true;
            }

        private void myport_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
            in_data = myport.ReadLine();
            this.Invoke(new EventHandler(saveline_event));
            }

        private void btn_disconnect_MouseClick(object sender, MouseEventArgs e)
            {
            try
                {
                myport.Close();
                }
            catch (Exception ex2)
                {
                MessageBox.Show(ex2.Message, "Oops...");
                }
            btn_disconnect.Enabled = false;
            btn_dwnload.Enabled = false;
            btn_count_files.Enabled = false;
            }

        private void btn_count_files_MouseClick(object sender, MouseEventArgs e)
            {
            myport.WriteLine("c"); //c for count
            try
                {
                file_number = Convert.ToInt16(myport.ReadLine());
                }
            catch (Exception ex2)
                {
                MessageBox.Show(ex2.Message, "No Answer");
                throw;
                }
            tb_count_files.Text = file_number.ToString();
            }

        private void btn_dwnload_MouseClick(object sender, MouseEventArgs e)
            {
            for (i = 0; i <= file_number; i++)
                {
                myport.WriteLine("n"); //send n for name
                try
                    {
                    filename = myport.ReadLine();
                    }
                catch (Exception ex3)
                    {
                    MessageBox.Show(ex3.Message, "No Answer");
                    throw;
                    }
                path = tb_pathname.Text;

                myport.WriteLine("s"); //send s for send file
                
                myport.DataReceived += myport_DataReceived; 

                }
            }
            
        private void saveline_event(object sender, EventArgs e)
            {
            System.IO.File.AppendAllText(path + filename, in_data);
            }

        private void btn_dwnload_Click(object sender, EventArgs e)
            {

            }
        }
    }

I can select the COM port, adjust the baudrate, connect and even get a correct file count.
Now, I am stuck.
I want to have a while loop incrementing up to the file number and sending the “n for name”, receive the filename, send the “s for send”, receive a stream of lines and file them away in the selected folder, under the received name.
It might be something like “while (in_data available) {System.IO.File.AppendAllText(path + filename, in_data);” but that is not quite it, it seems. I could propably use a timeout to increment and go to the next file, but that would not be very elegant.
I do not want a readymade solution, just guidance. I like to learn this way and am surely not the only one in this forum. It would be great to have an application like this and make the solution available to the community, wouldn’t it?
Thanks very much for any help!
Cheers