public async Task TestConvertFileSystemToGraphAsyncTaskWithoutHashWithoutPersistence()
        {
            var asyncFileReadBlockSize = 4096;
            var enableHash             = false;
            //var partitionInfoEx = new PartitionInfoEx(Hardware.Enumerations.PartitionFileSystem.NTFS, new UnitsNet.Information(1.2m, UnitsNet.Units.InformationUnit.Terabyte), new List<char>() { 'E' }, new Philote.Philote<IPartitionInfoEx>().Now());
            //var root = partitionInfoEx.DriveLetters.First();
            var root = 'E';
            // In Windows, root is a single letter, but in *nix, root is a string. Convert the single char to a string
            // ToDo: replace with ATAP.Utilities RunTimeKind, and make it *nix friendly
            var rootstring = root.ToString() + ":/";
            // Create storage for the results and progress
            var convertFileSystemToGraphProgress = new ConvertFileSystemToGraphProgress();
            // Cancellation token for the task
            var cancellationTokenSource   = new CancellationTokenSource();
            var cancellationTokenSourceId = new IdAsStruct <CancellationTokenSource>(Guid.NewGuid());
            var cancellationToken         = cancellationTokenSource.Token;
            ConvertFileSystemToGraphResult convertFileSystemToGraphResult;
            Stopwatch stopWatch = new Stopwatch();

            stopWatch.Start();
            try {
                Func <Task <ConvertFileSystemToGraphResult> > run = () => StaticExtensions.ConvertFileSystemToGraphAsyncTask(rootstring, asyncFileReadBlockSize, enableHash, convertFileSystemToGraphProgress, null, null, cancellationToken);
                convertFileSystemToGraphResult = await run.Invoke().ConfigureAwait(false);
            }
            catch (Exception) {
                throw;
            }
            finally {
                cancellationTokenSource.Dispose();
            }
            stopWatch.Stop();
            convertFileSystemToGraphResult.FSEntityAdjacencyGraph.VertexCount.Should().Be(15);
            convertFileSystemToGraphResult.FSEntityAdjacencyGraph.EdgeCount.Should().Be(16);
        }
        public async Task TestConvertFileSystemToGraphAsyncTaskWithoutHashWithoutPersistenceToDigraph()
        {
            var asyncFileReadBlockSize = 4096;
            var enableHash             = false;
            //var partitionInfoEx = new PartitionInfoEx(Hardware.Enumerations.PartitionFileSystem.NTFS, new UnitsNet.Information(1.2m, UnitsNet.Units.InformationUnit.Terabyte), new List<char>() { 'E' }, new Philote.Philote<IPartitionInfoEx>().Now());
            //var root = partitionInfoEx.DriveLetters.First();
            var root = 'E';
            // In Windows, root is a single letter, but in *nix, root is a string. Convert the single char to a string
            // ToDo: replace with ATAP.Utilities RunTimeKind, and make it *nix friendly
            var rootstring = root.ToString() + ":/";
            // Create storage for the results and progress
            var convertFileSystemToGraphProgress = new ConvertFileSystemToGraphProgress();
            // Cancellation token for the task
            var cancellationTokenSource   = new CancellationTokenSource();
            var cancellationTokenSourceId = new IdAsStruct <CancellationTokenSource>(Guid.NewGuid());
            var cancellationToken         = cancellationTokenSource.Token;
            ConvertFileSystemToGraphResult convertFileSystemToGraphResult;
            Stopwatch stopWatch = new Stopwatch();

            stopWatch.Start();
            try {
                Func <Task <ConvertFileSystemToGraphResult> > run = () => StaticExtensions.ConvertFileSystemToGraphAsyncTask(rootstring, asyncFileReadBlockSize, enableHash, convertFileSystemToGraphProgress, null, null, cancellationToken);
                convertFileSystemToGraphResult = await run.Invoke().ConfigureAwait(false);
            }
            catch (Exception) {
                throw;
            }
            finally {
                cancellationTokenSource.Dispose();
            }
            stopWatch.Stop();
            var digraph = new StringBuilder();

            digraph.Append("digraph G {"); digraph.Append(Environment.NewLine);
            foreach (var e in (convertFileSystemToGraphResult.FSEntityAdjacencyGraph.Edges
                               .Select(edge => {
                string fs = edge.Source.GetFullName();
                string ts = edge.Target.GetFullName();
                var tu = (fs, ts);
                return(tu);
            })).ToList <(string, string)>())
            {
                digraph.Append($"\"{e.Item1.Replace("\\", "\\\\")}\" -> \"{e.Item2.Replace("\\", "\\\\")}\""); digraph.Append(Environment.NewLine);
            }
            digraph.Append("}");
#if DEBUG
            TestOutput.WriteLine($"{digraph}");
#endif
            convertFileSystemToGraphResult.FSEntityAdjacencyGraph.VertexCount.Should().Be(15);
        }
        public async Task TestConvertFileSystemToGraphAsyncTaskFileWithoutHashWithPersistence()
        {
            // Arrange
            var asyncFileReadBlockSize = 4096;
            var enableHash             = false;

            //var partitionInfoEx = new PartitionInfoEx(Hardware.Enumerations.PartitionFileSystem.NTFS, new UnitsNet.Information(1.2m, UnitsNet.Units.InformationUnit.Terabyte), new List<char>() { 'E' }, new Philote.Philote<IPartitionInfoEx>().Now());
            //var root = partitionInfoEx.DriveLetters.First();
            var root = 'E';
            // In Windows, root is a single letter, but in *nix, root is a string. Convert the single char to a string
            // ToDo: replace with ATAP.Utilities RunTimeKind, and make it *nix friendly
            var rootstring = root.ToString() + ":/";
            // Create storage for the results and progress
            var convertFileSystemToGraphProgress = new ConvertFileSystemToGraphProgress();
            // Cancellation token for the task
            var cancellationTokenSource   = new CancellationTokenSource();
            var cancellationTokenSourceId = new IdAsStruct <CancellationTokenSource>(Guid.NewGuid());
            var cancellationToken         = cancellationTokenSource.Token;
            // PersistenceViaFiles
            // Create temporary files to hold the persistence data
            var numfiles       = 2;
            var temporaryFiles = new TemporaryFile[numfiles];
            var filePaths      = new string[2];

            for (int i = 0; i < 2; i++)
            {
                temporaryFiles[i] = new TemporaryFile().CreateTemporaryFileEmpty();
                filePaths[i]      = temporaryFiles[i].FileInfo.FullName;
#if DEBUG
                TestOutput.WriteLine($"File {i} is named {temporaryFiles[i].FileInfo.FullName}");
#endif
            }

            // Call the SetupViaFileFuncBuilder here, execute the Func that comes back, with filePaths as the argument
            var setupResults = ATAP.Utilities.Persistence.Extensions.SetupViaFileFuncBuilder()(new SetupViaFileData(filePaths));

            //var insertFunc = InsertViaFileFuncBuilder(setupResults);
            // Create an insertFunc that references the local variable setupResults, closing over it
            var insertFunc = new Func <IEnumerable <IEnumerable <object> >, IInsertViaFileResults>((insertData) => {
                int numberOfFiles = insertData.ToArray().Length;
#if DEBUG
                TestOutput.WriteLine($"Got {numberOfFiles} arrays of data to write");
#endif
                int numberOfStreamWriters = setupResults.StreamWriters.Length;
#if DEBUG
                TestOutput.WriteLine($"Got {numberOfStreamWriters} streamwriters to write to");
#endif
                for (var i = 0; i < numberOfFiles; i++)
                {
                    foreach (string str in insertData.ToArray()[i])
                    {
                        //ToDo: add async versions await setupResults.StreamWriters[i].WriteLineAsync(str);
                        //ToDo: exception handling
                        setupResults.StreamWriters[i].WriteLine(str);
#if DEBUG
                        TestOutput.WriteLine($"writing {str} to file {i}");
#endif
                    }
                }
                return(new InsertViaFileResults(true));
            });

            Persistence <IInsertResultsAbstract> persistence = new Persistence <IInsertResultsAbstract>(insertFunc);
            ConvertFileSystemToGraphResult       convertFileSystemToGraphResult;
            // Act
            try {
                Func <Task <ConvertFileSystemToGraphResult> > run = () => StaticExtensions.ConvertFileSystemToGraphAsyncTask(rootstring, asyncFileReadBlockSize, enableHash, convertFileSystemToGraphProgress, persistence, null, cancellationToken);
                convertFileSystemToGraphResult = await run.Invoke().ConfigureAwait(false);
            }
            catch (Exception) {
                throw;
            }
            finally {
                setupResults.Dispose();
                cancellationTokenSource.Dispose();
            }

            //Assert
            convertFileSystemToGraphResult.FSEntityAdjacencyGraph.VertexCount.Should().Be(15);
            convertFileSystemToGraphResult.FSEntityAdjacencyGraph.EdgeCount.Should().Be(14);
            // Convert the IList objects to List objects
            List <FSEntityAbstract>            verticesAsAbstract = convertFileSystemToGraphResult.FSEntityAdjacencyGraph.Vertices.ToList();
            List <FSEEdge <FSEntityAbstract> > edgesAsAbstract    = convertFileSystemToGraphResult.FSEntityAdjacencyGraph.Edges.ToList();
            verticesAsAbstract.Count.Should().Be(15);
            edgesAsAbstract.Count.Should().Be(14);
            List <string> verticesAsString = verticesAsAbstract.Select(x => x.GetFullName()).ToList();
            List <string> edgesAsString    = edgesAsAbstract.Select((x) => x.Source.GetFullName() + " -> " + x.Target.GetFullName()).ToList();;
            List <string> verticesfromFile = File.ReadLines(temporaryFiles[0].FileInfo.FullName).ToList();
            List <string> edgesfromFile    = File.ReadLines(temporaryFiles[1].FileInfo.FullName).ToList();
#if DEBUG
            TestOutput.WriteLine($"File 0 (vertices) contains {verticesfromFile.Count} vertices");
            foreach (var str in verticesfromFile)
            {
                TestOutput.WriteLine(str);
            }
            TestOutput.WriteLine($"File 1 (edges) contains {edgesfromFile.Count} edges");
            foreach (var str in edgesfromFile)
            {
                TestOutput.WriteLine(str);
            }
#endif
            verticesAsString.Should().BeEquivalentTo(verticesfromFile);
            edgesAsString.Should().BeEquivalentTo(edgesfromFile);
        }
        async Task DoLoopAsync(string inputLine)
        {
            // check CancellationToken to see if this task is canceled
            CheckAndHandleCancellationToken(1);

            logger.LogDebug(uiLocalizer["{0} {1} inputLineString = {2}", "Console03BackgroundService", "DoLoopAsync", inputLine]);

            // Echo to stdOut the line that came in on stdIn
            mesg.Append(uiLocalizer["You selected: {0}", inputLine]);
            #region Write the mesg to stdout
            using (Task task = await WriteMessageSafelyAsync().ConfigureAwait(false)) {
                if (!task.IsCompletedSuccessfully)
                {
                    if (task.IsCanceled)
                    {
                        // Ignore if user cancelled the operation during output to stdout (internal cancellation)
                        // re-throw if the cancellation request came from outside the stdInLineMonitorAction
                        /// ToDo: evaluate the linked, inner, and external tokens
                        throw new OperationCanceledException();
                    }
                    else if (task.IsFaulted)
                    {
                        //ToDo: Go through the inner exception
                        //foreach (var e in t.Exception) {
                        //  https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors
                        // ToDo figure out what to do if the output stream is closed
                        throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException");
                        //}
                    }
                }
                mesg.Clear();
            }
            #endregion
            #region tempout
            switch (inputLine)
            {
            case "1":
                // ToDo: Get these from the Console03 application configuration
                // ToDo: Get these from the database or from a configurationRoot (priority?)
                string GenerateProgramDBConnectionString = "";
                Philote <GAssemblyGroup>                   assemblyGroupPhilote       = new Philote <GAssemblyGroup>();
                Philote <GSolutionGroupSignil>             solutionGroupSignilPhilote = new Philote <GSolutionGroupSignil>();
                Philote <GGlobalCreateBuildtestDeployKVPs> gGlobalCreateBuildtestDeployKVPsPhilote = new Philote <GGlobalCreateBuildtestDeployKVPs>();
                var enableProgress = appConfiguration.GetValue <bool>(appStringConstants.EnableProgressBoolConfigRootKey, bool.Parse(appStringConstants.EnableProgressBoolDefault));// ToDo: should validate in case the appStringConstants assembly is messed up?
                // var enablePersistence = appConfiguration.GetValue<bool>(appStringConstants.EnablePersistenceBoolConfigRootKey, bool.Parse(appStringConstants.EnablePersistenceBoolDefault));// ToDo: should validate in case the appStringConstants assembly is messed up?
                // var enablePickAndSave = appConfiguration.GetValue<bool>(appStringConstants.EnablePickAndSaveBoolConfigRootKey, bool.Parse(appStringConstants.EnablePickAndSaveBoolDefault));// ToDo: should validate in case the appStringConstants assembly is messed up?
                var temporaryDirectoryBase = appConfiguration.GetValue <string>(appStringConstants.TemporaryDirectoryBaseConfigRootKey, appStringConstants.TemporaryDirectoryBaseDefault);
                // var WithPersistenceNodeFileRelativePath = appConfiguration.GetValue<string>(appStringConstants.WithPersistenceNodeFileRelativePathConfigRootKey, appStringConstants.WithPersistenceNodeFileRelativePathDefault);
                // var WithPersistenceEdgeFileRelativePath = appConfiguration.GetValue<string>(appStringConstants.WithPersistenceEdgeFileRelativePathConfigRootKey, appStringConstants.WithPersistenceEdgeFileRelativePathDefault);
                // var filePathsPersistence = new string[2] { temporaryDirectoryBase + WithPersistenceNodeFileRelativePath, temporaryDirectoryBase + WithPersistenceEdgeFileRelativePath };
                // var WithPickAndSaveNodeFileRelativePath = appConfiguration.GetValue<string>(appStringConstants.WithPickAndSaveNodeFileRelativePathConfigRootKey, appStringConstants.WithPickAndSaveNodeFileRelativePathDefault);
                // var filePathsPickAndSave = new string[1] { temporaryDirectoryBase + WithPickAndSaveNodeFileRelativePath };

                mesg.Append(uiLocalizer["Running GenerateProgram Function on the AssemblyGroupKey {0}, with GlobalSettingsKey {1} and SolutionSignilKey {2}", "Console03Mechanical", "ATAPStandardGlobalSettingsKey", "ATAPStandardGSolutionSignilKey"]);

                #region Write the mesg to stdout
                using (Task task = await WriteMessageSafelyAsync().ConfigureAwait(false)) {
                    if (!task.IsCompletedSuccessfully)
                    {
                        if (task.IsCanceled)
                        {
                            // Ignore if user cancelled the operation during output to stdout (internal cancellation)
                            // re-throw if the cancellation request came from outside the stdInLineMonitorAction
                            /// ToDo: evaluate the linked, inner, and external tokens
                            throw new OperationCanceledException();
                        }
                        else if (task.IsFaulted)
                        {
                            //ToDo: Go through the inner exception
                            //foreach (var e in t.Exception) {
                            //  https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors
                            // ToDo figure out what to do if the output stream is closed
                            throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException");
                            //}
                        }
                    }
                    mesg.Clear();
                }
                #endregion
                // Connect to the GenerateProgramDB

                // Get GlobalSettingsSignil using GlobalSettingsKey
                // Get the SolutionGroupKey from the DB using the ProgramKey
                // get the SolutionGroupSignil from the DB using the SolutionGroupKey

                #region ProgressReporting setup
                ConvertFileSystemToGraphProgress?convertFileSystemToGraphProgress;;
                if (enableProgress)
                {
                    convertFileSystemToGraphProgress = new ConvertFileSystemToGraphProgress();
                }
                else
                {
                    convertFileSystemToGraphProgress = null;
                }
                #endregion

                /* Persistence is not used in the Console03 Background Serveice nor in the GenerateProgram entry points it calls
                 *
                 #region PersistenceViaFiles setup
                 * // Ensure the Node and Edge files are empty and can be written to
                 * // Call the SetupViaFileFuncBuilder here, execute the Func that comes back, with filePaths as the argument
                 * // ToDo: create a function that will create subdirectories if needed to fulfill path, and use that function when creating the temp files
                 * //ToDo: add exception handling if the setup function fails
                 * ISetupViaFileResults setupResultsPersistence;
                 * try {
                 * setupResultsPersistence = PersistenceStaticExtensions.SetupViaFileFuncBuilder()(new SetupViaFileData(filePathsPersistence));
                 * }
                 * catch (System.IO.IOException ex) {
                 * // prepare message for UI interface
                 * // ToDo: custom exception,  and include its message here
                 * mesg.Append(uiLocalizer["IOException trying to setup PersistenceViaFiles"]);
                 *
                 #region Write the mesg to stdout
                 * using (Task task = await WriteMessageSafelyAsync().ConfigureAwait(false)) {
                 *  if (!task.IsCompletedSuccessfully) {
                 *    if (task.IsCanceled) {
                 *      // Ignore if user cancelled the operation during output to stdout (internal cancellation)
                 *      // re-throw if the cancellation request came from outside the stdInLineMonitorAction
                 *      /// ToDo: evaluate the linked, inner, and external tokens
                 *      throw new OperationCanceledException();
                 *    }
                 *    else if (task.IsFaulted) {
                 *      //ToDo: Go through the inner exception
                 *      //foreach (var e in t.Exception) {
                 *      //  https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors
                 *      // ToDo figure out what to do if the output stream is closed
                 *      throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException");
                 *      //}
                 *    }
                 *  }
                 *  mesg.Clear();
                 * }
                 #endregion
                 * // Throw exception, Cancel the entire service (internal CTS), or swallow and Continue (possibly offering hints as to resolution), client's choice
                 * throw ex;
                 * // internalCancellationTokenSource.Signal ????
                 * // or just continue and let the user make another selection or go fix the problem
                 * //break;
                 * }
                 * // Create an insertFunc that references the local variable setupResults, closing over it
                 * var insertFunc = new Func<IEnumerable<IEnumerable<object>>, IInsertViaFileResults>((insertData) => {
                 * int numberOfDatas = insertData.ToArray().Length;
                 * int numberOfStreamWriters = setupResultsPersistence.StreamWriters.Length;
                 * for (var i = 0; i < numberOfDatas; i++) {
                 *  foreach (string str in insertData.ToArray()[i]) {
                 *    //ToDo: add async versions await setupResults.StreamWriters[i].WriteLineAsync(str);
                 *    //ToDo: exception handling
                 *    setupResultsPersistence.StreamWriters[i].WriteLine(str);
                 *  }
                 * }
                 * return new InsertViaFileResults(true);
                 * });
                 * Persistence<IInsertResultsAbstract> persistence = new Persistence<IInsertResultsAbstract>(insertFunc);
                 #endregion
                 */
                /* PickAndSave is not used in the Console03 Background Serveice nor in the GenerateProgram entry points it calls
                 #region PickAndSaveViaFiles setup
                 * // Ensure the Archived files are empty and can be written to
                 * // Call the SetupViaFileFuncBuilder here, execute the Func that comes back, with filePathsPickAndSave as the argument
                 * // ToDo: create a function that will create subdirectories if needed to fulfill path, and use that function when creating the temp files
                 * ISetupViaFileResults setupResultsPickAndSave;
                 * try {
                 * setupResultsPickAndSave = PersistenceStaticExtensions.SetupViaFileFuncBuilder()(new SetupViaFileData(filePathsPickAndSave));
                 * }
                 * catch (System.IO.IOException ex) {
                 * // prepare message for UI interface
                 * // ToDo: custom exception,  and include its message here
                 * mesg.Append(uiLocalizer["IOException trying to setup PickAndSaveViaFiles"]);
                 #region Write the mesg to stdout
                 * using (Task task = await WriteMessageSafelyAsync().ConfigureAwait(false)) {
                 *  if (!task.IsCompletedSuccessfully) {
                 *    if (task.IsCanceled) {
                 *      // Ignore if user cancelled the operation during output to stdout (internal cancellation)
                 *      // re-throw if the cancellation request came from outside the stdInLineMonitorAction
                 *      /// ToDo: evaluate the linked, inner, and external tokens
                 *      throw new OperationCanceledException();
                 *    }
                 *    else if (task.IsFaulted) {
                 *      //ToDo: Go through the inner exception
                 *      //foreach (var e in t.Exception) {
                 *      //  https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors
                 *      // ToDo figure out what to do if the output stream is closed
                 *      throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException");
                 *      //}
                 *    }
                 *  }
                 *  mesg.Clear();
                 * }
                 #endregion
                 * // Throw exception, Cancel the entire service (internal CTS), or swallow and Continue (possibly offering hints as to resolution), client's choice
                 * throw ex;
                 * // internalCancellationTokenSource.Signal ????
                 * // or just continue and let the user make another selection or go fix the problem
                 * //break;
                 * }
                 * // Create a pickFunc (AKA Predicate)
                 * var pickFuncPickAndSave = new Func<object, bool>((objToTest) => {
                 * return FileIOExtensions.IsArchiveFile(objToTest.ToString()) || FileIOExtensions.IsMailFile(objToTest.ToString());
                 * });
                 * // Create an insert Func
                 * var insertFuncPickAndSave = new Func<IEnumerable<IEnumerable<object>>, IInsertViaFileResults>((insertData) => {
                 * int numberOfStreamWriters = setupResultsPickAndSave.StreamWriters.Length;
                 * for (var i = 0; i < numberOfStreamWriters; i++) {
                 *  foreach (string str in insertData.ToArray()[i]) {
                 *    //ToDo: add async versions await setupResults.StreamWriters[i].WriteLineAsync(str);
                 *    //ToDo: exception handling
                 *    // ToDo: Make formatting a parameter
                 *    try {
                 *      setupResultsPickAndSave.StreamWriters[i].WriteLine(str);
                 *    }
                 *    catch (System.IO.IOException ex) {
                 *
                 *      throw;
                 *    }
                 *  }
                 * }
                 * return new InsertViaFileResults(true);
                 * });
                 * PickAndSave<IInsertResultsAbstract> pickAndSave = new PickAndSave<IInsertResultsAbstract>(pickFuncPickAndSave, insertFuncPickAndSave);
                 #endregion
                 */

                GGenerateProgramResult gGenerateProgramResult;
                #region Method timing setup
                Stopwatch stopWatch = new Stopwatch(); // ToDo: utilize a much more powerfull and ubiquitous timing and profiling tool than a stopwatch
                stopWatch.Start();
                #endregion
                try {
                    Func <Task <GGenerateProgramResult> > run = () => GenerateProgram.GenerateProgram(gGenerateProgramSignil);
                    gGenerateProgramResult = await run.Invoke().ConfigureAwait(false);

                    stopWatch.Stop(); // ToDo: utilize a much more powerfull and ubiquitous timing and profiling tool than a stopwatch
                                      // ToDo: put the results someplace
                }
                catch (Exception) {   // ToDo: define explicit exceptions to catch and report upon
                                      // ToDo: catch FileIO.FileNotFound, sometimes the file disappears
                    throw;
                }
                finally {
                    // Dispose of the objects that need disposing

                    /* PickAndSave is not used in the Console03 Background Serveice nor in the GenerateProgram entry points it calls
                     * setupResultsPickAndSave.Dispose();
                     */
                    /* Persistence is not used in the Console03 Background Serveice nor in the GenerateProgram entry points it calls
                     * setupResultsPersistence.Dispose();
                     */
                }
                #region Build the results
                BuildGenerateProgramResults(mesg, gGenerateProgramResult, stopWatch);
                #endregion

                break;
            //    case "2":
            //      #region define the Func<string,Task> to be executed when the ConsoleSourceHostedService.ConsoleReadLineAsyncAsObservable produces a sequence element
            //      // This Action closes over the current local variables' values
            //      Func<string, Task> SimpleEchoToConsoleOutFunc = new Func<string, Task>(async (inputLineString) => {
            //        #region Write the mesg to stdout
            //        using (Task task = await WriteMessageSafelyAsync(inputLineString, consoleSinkHostedService, linkedCancellationToken).ConfigureAwait(false)) {
            //          if (!task.IsCompletedSuccessfully) {
            //            if (task.IsCanceled) {
            //              // Ignore if user cancelled the operation during output to stdout (internal cancellation)
            //              // re-throw if the cancellation request came from outside the stdInLineMonitorAction
            //              /// ToDo: evaluate the linked, inner, and external tokens
            //              throw new OperationCanceledException();
            //            }
            //            else if (task.IsFaulted) {
            //              //ToDo: Go through the inner exception
            //              //foreach (var e in t.Exception) {
            //              //  https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors
            //              // ToDo figure out what to do if the output stream is closed
            //              throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException");
            //              //}
            //            }
            //          }
            //        }
            //        #endregion

            //      });
            //      #endregion
            //      break;
            //    case "10":
            //      #region setup a local block for handling this choice
            //      try {
            //        var enableHash = configurationRoot.GetValue<bool>(ConsoleMonitorStringConstants.EnableHashBoolConfigRootKey, bool.Parse(ConsoleMonitorStringConstants.EnableHashBoolConfigRootKeyDefault));  // ToDo: should validate in case the ConsoleMonitorStringConstants assembly is messed up?
            //        var enableProgress = configurationRoot.GetValue<bool>(ConsoleMonitorStringConstants.EnableProgressBoolConfigRootKey, bool.Parse(ConsoleMonitorStringConstants.EnableProgressBoolDefault));// ToDo: should validate in case the ConsoleMonitorStringConstants assembly is messed up?
            //        var enablePersistence = configurationRoot.GetValue<bool>(ConsoleMonitorStringConstants.EnablePersistenceBoolConfigRootKey, bool.Parse(ConsoleMonitorStringConstants.EnablePersistenceBoolDefault));// ToDo: should validate in case the ConsoleMonitorStringConstants assembly is messed up?
            //        var enablePickAndSave = configurationRoot.GetValue<bool>(ConsoleMonitorStringConstants.EnablePickAndSaveBoolConfigRootKey, bool.Parse(ConsoleMonitorStringConstants.EnablePickAndSaveBoolDefault));// ToDo: should validate in case the ConsoleMonitorStringConstants assembly is messed up?
            //        var dBConnectionString = configurationRoot.GetValue<string>(ConsoleMonitorStringConstants.DBConnectionStringConfigRootKey, ConsoleMonitorStringConstants.DBConnectionStringDefault);// ToDo: should validate in case the ConsoleMonitorStringConstants assembly is messed up?
            //                                                                                                                                                                                            // ToDo: This should be a string representation of a known enumeration of ORMLite DB providers that this service can support
            //        var dBProvider = configurationRoot.GetValue<string>(ConsoleMonitorStringConstants.DBConnectionStringConfigRootKey, ConsoleMonitorStringConstants.DBConnectionStringDefault);// ToDo: should validate in case the ConsoleMonitorStringConstants assembly is messed up?
            //        dBProvider = SqlServerOrmLiteDialectProvider.Instance;
            //        #region ProgressReporting setup
            //        ConvertFileSystemToGraphProgress? convertFileSystemToGraphProgress;
            //        if (enableProgress) {
            //          convertFileSystemToGraphProgress = new ConvertFileSystemToGraphProgress();
            //        }
            //        else {
            //          convertFileSystemToGraphProgress = null;
            //        }
            //        #endregion
            //        #region PersistenceViaIORMSetup
            //        // Call the SetupViaIORMFuncBuilder here, execute the Func that comes back, with dBConnectionString as the argument
            //        // Ensure the NNode and Edge Tables for this PartitionInfo are empty and can be written to
            //        // ToDo: create a function that will create Node and Edge tables if they don't yet exist, and use that function when creating the temp fiiles
            //        // ToDo: add exception handling if the setup function fails
            //        var setupResultsPersistence = PersistenceStaticExtensions.SetupViaORMFuncBuilder()(new SetupViaORMData(dBConnectionString, dBProvider, linkedCancellationToken));

            //        // Create an insertFunc that references the local variable setupResults, closing over it
            //        var insertFunc = new Func<IEnumerable<IEnumerable<object>>, IInsertViaORMResults>((insertData) => {
            //          int numberOfDatas = insertData.ToArray().Length;
            //          int numberOfStreamWriters = setupResultsPersistence.StreamWriters.Length;
            //          for (var i = 0; i < numberOfDatas; i++) {
            //            foreach (string str in insertData.ToArray()[i]) {
            //              //ToDo: add async versions await setupResults.StreamWriters[i].WriteLineAsync(str);
            //              //ToDo: exception handling
            //              setupResultsPersistence.Tables[i].SQLCmd(str);
            //            }
            //          }
            //          return new InsertViaORMResults(true);
            //        });
            //        Persistence<IInsertResultsAbstract> persistence = new Persistence<IInsertResultsAbstract>(insertFunc);
            //        #endregion
            //        #region PickAndSaveViaIORM setup
            //        // Ensure the Node and Edge files are empty and can be written to

            //        // Call the SetupViaIORMFuncBuilder here, execute the Func that comes back, with filePaths as the argument
            //        // ToDo: create a function that will create subdirectories if needed to fulfill path, and use that function when creating the temp files
            //        var setupResultsPickAndSave = PersistenceStaticExtensions.SetupViaORMFuncBuilder()(new SetupViaORMData(dBConnectionString, dBProvider, linkedCancellationToken));
            //        // Create a pickFunc
            //        var pickFuncPickAndSave = new Func<object, bool>((objToTest) => {
            //          return FileIOExtensions.IsArchiveFile(objToTest.ToString()) || FileIOExtensions.IsMailFile(objToTest.ToString());
            //        });
            //        // Create an insert Func
            //        var insertFuncPickAndSave = new Func<IEnumerable<IEnumerable<object>>, IInsertViaORMResults>((insertData) => {
            //          //int numberOfStreamWriters = setupResultsPickAndSave.StreamWriters.Length;
            //          //for (var i = 0; i < numberOfStreamWriters; i++) {
            //          //  foreach (string str in insertData.ToArray()[i]) {
            //          //    //ToDo: add async versions await setupResults.StreamWriters[i].WriteLineAsync(str);
            //          //    //ToDo: exception handling
            //          //    // ToDo: Make formatting a parameter
            //          //    setupResultsPickAndSave.StreamWriters[i].WriteLine(str);
            //          //  }
            //          //}
            //          return new InsertViaORMResults(true);
            //        });
            //        PickAndSave<IInsertResultsAbstract> pickAndSave = new PickAndSave<IInsertResultsAbstract>(pickFuncPickAndSave, insertFuncPickAndSave);
            //        #endregion
            //      }
            //      // To Catch specific exceptions that might occur
            //      catch {
            //      }
            //      // ToDo: dispose
            //      finally { }
            //      #endregion
            //      break;
            case "99":
                #region Quit the program
                //internalcancellationtoken.
                #endregion
                break;

            default:
                mesg.Clear();
                mesg.Append(uiLocalizer["InvalidInputDoesNotMatchAvailableChoices {0}", inputLine]);
                break;
            }

            #region Write the mesg to stdout
            using (Task task = await WriteMessageSafelyAsync().ConfigureAwait(false)) {
                if (!task.IsCompletedSuccessfully)
                {
                    if (task.IsCanceled)
                    {
                        // Ignore if user cancelled the operation during output to stdout (internal cancellation)
                        // re-throw if the cancellation request came from outside the stdInLineMonitorAction
                        /// ToDo: evaluate the linked, inner, and external tokens
                        throw new OperationCanceledException();
                    }
                    else if (task.IsFaulted)
                    {
                        //ToDo: Go through the inner exception
                        //foreach (var e in t.Exception) {
                        //  https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors
                        // ToDo figure out what to do if the output stream is closed
                        throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException");
                        //}
                    }
                }
            }
            #endregion

            #endregion
            #region Buildmenu
            await BuildMenu();

            #endregion
            #region Write the mesg to stdout
            using (Task task = await WriteMessageSafelyAsync().ConfigureAwait(false)) {
                if (!task.IsCompletedSuccessfully)
                {
                    if (task.IsCanceled)
                    {
                        // Ignore if user cancelled the operation during output to stdout (internal cancellation)
                        // re-throw if the cancellation request came from outside the stdInLineMonitorAction
                        /// ToDo: evaluate the linked, inner, and external tokens
                        throw new OperationCanceledException();
                    }
                    else if (task.IsFaulted)
                    {
                        //ToDo: Go through the inner exception
                        //foreach (var e in t.Exception) {
                        //  https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors
                        // ToDo figure out what to do if the output stream is closed
                        throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException");
                        //}
                    }
                }
                mesg.Clear();
            }
            #endregion
        }