static void Main(string[] args)
        {
            Options arguments = Parser.Default.ParseArguments <Options>(args).MapResult(options => options, _ => null);
            Logger  logger    = new Logger(true, arguments.LogFile != null ? arguments.LogFile : null);

            logger.Log("Started");

            // Server

            logger.Log($"Connecting to server {arguments.ServerName}");
            PIServer piServer = PIUtil.GetPIServer(arguments.ServerName);

            logger.Log($"Connecting to system {arguments.SystemName}");
            PISystem piSystem = AFUtil.GetPISystem(arguments.SystemName);

            logger.Log("Connected");

            // Tags

            logger.Log($"Reading tags from {arguments.InputFile}");

            List <AbstractRetrievePoints> tagClasses = null;

            switch (arguments.InputType)
            {
            case "RecordedTag":
                tagClasses = MainFunctions.LoadTagClassesRecorded(
                    arguments.InputFile,
                    arguments.OutputDirectory,
                    arguments.TimeResolution,
                    arguments.NumYears,
                    arguments.PageSize,
                    piServer,
                    piSystem,
                    arguments.NumParallelTasks,
                    logger);
                break;

            case "InterpolatedTag":
                tagClasses = MainFunctions.LoadTagClassesInterpolated(
                    arguments.InputFile,
                    arguments.OutputDirectory,
                    arguments.TimeResolution,
                    arguments.NumYears,
                    arguments.PageSize,
                    piServer,
                    piSystem,
                    arguments.NumParallelTasks,
                    logger);
                break;

            case "RecordedAttribute":
                tagClasses = MainFunctions.LoadAttributeClassesRecorded(
                    arguments.InputFile,
                    arguments.OutputDirectory,
                    arguments.TimeResolution,
                    arguments.NumYears,
                    arguments.PageSize,
                    piServer,
                    piSystem,
                    AFUtil.GetDatabase(piSystem, arguments.DatabaseName),
                    arguments.NumParallelTasks,
                    logger);
                break;

            case "InterpolatedAttribute":
                tagClasses = MainFunctions.LoadAttributeClassesInterpolated(
                    arguments.InputFile,
                    arguments.OutputDirectory,
                    arguments.TimeResolution,
                    arguments.NumYears,
                    arguments.PageSize,
                    piServer,
                    piSystem,
                    AFUtil.GetDatabase(piSystem, arguments.DatabaseName),
                    arguments.NumParallelTasks,
                    logger);
                break;

            default:
                break;
            }
            logger.Log($"Tags read");

            logger.Log($"Reading tag data from {arguments.ServerName}, numParallelTasks = {arguments.NumParallelTasks}");
            MainFunctions.DoStuffParallelForeach(tagClasses, arguments.NumParallelTasks, logger);
            logger.Log($"Data read");

            logger.Log("Finished - press Enter to close terminal");
            logger.Close();
            Console.ReadLine();
        }