public static void Main()

in src/Azure.IIoT.OpcUa.Publisher.Module/cli/Program.cs [42:350]


        public static void Main(string[] args)
        {
            var checkTrust = false;
            var withServer = false;
            string? deviceId = null, moduleId = null;
            int? reverseConnectPort = null;

            var loggerFactory = Log.ConsoleFactory();
            var logger = loggerFactory.CreateLogger<PublisherModule>();

            logger.LogInformation("Publisher module command line interface.");
            var instances = 1;
            string? connectionString = null;
            string? publishProfile = null;
            string? publishInitProfile = null;
            string? publishInitFilePath = null;
            string? publishedNodesFilePath = null;
            var useNullTransport = false;
            string? dumpMessages = null;
            string? dumpMessagesOutput = null;
            var scaleunits = 0u;
            var errorResponseRate = 0;
            var unknownArgs = new List<string>();
            try
            {
                for (var i = 0; i < args.Length; i++)
                {
                    switch (args[i])
                    {
                        case "--error-rate":
                            i++;
                            if (i < args.Length && int.TryParse(args[i], out var rate))
                            {
                                errorResponseRate = rate;
                                break;
                            }
                            throw new ArgumentException("Missing argument for --error-rate");
                        case "--dump-profiles":
                            Console.WriteLine();
                            Console.WriteLine();
                            Console.WriteLine("The following messaging profiles are supported (selected with --mm and --me):");
                            Console.WriteLine();
                            Console.Write(MessagingProfile.GetAllAsMarkdownTable());
                            return;
                        case "-C":
                        case "--connection-string":
                            i++;
                            if (i < args.Length)
                            {
                                connectionString = args[i];
                                break;
                            }
                            throw new ArgumentException(
                                "Missing argument for --connection-string");
                        case "-?":
                        case "-h":
                        case "--help":
                            throw new ArgumentException("Help");
                        case "-N":
                        case "--instances":
                            i++;
                            if (i < args.Length && int.TryParse(args[i], out instances))
                            {
                                break;
                            }
                            throw new ArgumentException("Missing argument for --instances");
                        case "-U":
                        case "--scale":
                            i++;
                            if (i < args.Length && uint.TryParse(args[i], out scaleunits))
                            {
                                withServer = true;
                                break;
                            }
                            throw new ArgumentException("Missing argument for --scale");
                        case "--reverse-connect":
                            reverseConnectPort = 4840;
                            break;
                        case "--port":
                            i++;
                            if (i < args.Length && int.TryParse(args[i], out var port))
                            {
                                reverseConnectPort = port;
                                break;
                            }
                            throw new ArgumentException("Missing argument for --port");
                        case "-T":
                        case "--only-trusted":
                            checkTrust = true;
                            break;
                        case "-X":
                        case "--out-null":
                            useNullTransport = true;
                            break;
                        case "-S":
                        case "--with-server":
                            withServer = true;
                            break;
                        case "-D":
                        case "--dump-messages":
                            i++;
                            useNullTransport = true;
                            if (i < args.Length)
                            {
                                dumpMessages = args[i];
                                break;
                            }
                            throw new ArgumentException("Missing argument for --dump-messages");
                        case "-O":
                        case "--dump-output":
                            i++;
                            if (i < args.Length)
                            {
                                dumpMessagesOutput = args[i];
                                break;
                            }
                            throw new ArgumentException("Missing argument for --dump-output");
                        case "-P":
                        case "--publish-profile":
                            i++;
                            if (i < args.Length)
                            {
                                publishProfile = args[i];
                                withServer = true;
                                break;
                            }
                            throw new ArgumentException("Missing argument for --publish-profile");
                        case "-I":
                        case "--init-profile":
                            i++;
                            if (i < args.Length)
                            {
                                publishInitProfile = args[i];
                                withServer = true;
                                break;
                            }
                            throw new ArgumentException("Missing argument for --init-profile");
                        case "--pnjson":
                            i++;
                            if (i < args.Length)
                            {
                                publishedNodesFilePath = args[i];
                                break;
                            }
                            throw new ArgumentException("Missing argument for --pnjson");
                        case "--init":
                            i++;
                            if (i < args.Length)
                            {
                                publishInitFilePath = args[i];
                                break;
                            }
                            throw new ArgumentException("Missing argument for --init");
                        case "--":
                            break;
                        default:
                            unknownArgs.Add(args[i]);
                            break;
                    }
                }

                if (string.IsNullOrEmpty(connectionString) && !useNullTransport)
                {
                    try
                    {
                        var configuration = new ConfigurationBuilder()
                            .AddFromDotEnvFile()
                            .AddEnvironmentVariables()
                            .AddFromKeyVault(ConfigurationProviderPriority.Lowest)
                            .Build();
                        connectionString = configuration.GetValue("PCS_IOTHUB_CONNSTRING", string.Empty);
                        if (string.IsNullOrEmpty(connectionString))
                        {
                            connectionString = configuration.GetValue("_HUB_CS", string.Empty);
                        }
                        if (!string.IsNullOrEmpty(connectionString) &&
                            !ConnectionString.TryParse(connectionString, out _))
                        {
                            throw new ArgumentException("Bad connection string configured.");
                        }
                    }
                    catch (Exception e)
                    {
                        logger.LogInformation("Error {Error}: Missing connection string - continue...",
                            e.Message);
                    }
                }

                deviceId = Dns.GetHostName().ToUpperInvariant();
                logger.LogInformation("Using <deviceId> '{DeviceId}'", deviceId);
                moduleId = "publisher";
                logger.LogInformation("Using <moduleId> '{ModuleId}'", moduleId);

                args = [.. unknownArgs];
            }
            catch (Exception e)
            {
                logger.LogError(
                    @"{Error}

Usage:       Azure.IIoT.OpcUa.Publisher.Module.Cli [options]

Options:
     -C
    --connection-string
             IoT Hub owner connection string to use to connect to IoT hub for
             operations on the registry.  If not provided, read from environment.

    --help
     -?
     -h      Prints out this help.
",
                    e.Message);
                return;
            }

            AppDomain.CurrentDomain.UnhandledException +=
                (s, e) => logger.LogError(e.ExceptionObject as Exception, "Exception");

            using var cts = new CancellationTokenSource();
            Task hostingTask;
            try
            {
                if (dumpMessages != null)
                {
                    hostingTask = DumpMessagesAsync(dumpMessages, publishProfile, publishInitProfile,
                        loggerFactory, TimeSpan.FromMinutes(2), scaleunits, errorResponseRate,
                        dumpMessagesOutput, args, cts.Token);
                }
                else if (!withServer)
                {
                    if (publishInitFilePath != null && !File.Exists(publishInitFilePath))
                    {
                        publishInitFilePath = $"./Initfiles/{publishInitFilePath}.init";
                        if (File.Exists(publishInitFilePath))
                        {
                            const string copyTo = "profile.init";
                            File.Copy(publishInitFilePath, copyTo, true);
                            File.SetLastWriteTimeUtc(copyTo, DateTime.UtcNow);
                            publishInitFilePath = copyTo;
                        }
                        else
                        {
                            publishInitFilePath = null;
                        }
                    }
                    hostingTask = HostAsync(connectionString, loggerFactory,
                        deviceId, moduleId, args, reverseConnectPort, !checkTrust,
                        publishInitFilePath, publishedNodesFilePath, cts.Token);
                }
                else
                {
                    hostingTask = WithServerAsync(connectionString, loggerFactory, deviceId,
                        moduleId, args, publishProfile, publishInitProfile, scaleunits,
                        errorResponseRate, !checkTrust, reverseConnectPort, cts.Token);
                }

                while (!cts.Token.IsCancellationRequested)
                {
                    var key = Console.ReadKey();
                    switch (key.KeyChar)
                    {
                        case 'X':
                        case 'x':
                            Console.WriteLine("Exiting...");
                            cts.Cancel();
                            break;
                        case 'P':
                        case 'p':
                            Console.WriteLine("Restarting publisher...");
                            kRestartPublisher.Set();
                            break;
                        case 'S':
                        case 's':
                            Console.WriteLine("Restarting server...");
                            kRestartServer.Set();
                            break;
                        case 'C':
                            Console.WriteLine("Closing sessions and subscriptions in server");
                            ServerControl?.CloseSessions(true);
                            break;
                        case 'c':
                            Console.WriteLine("Closing sessions in server");
                            ServerControl?.CloseSessions(false);
                            break;
                        case 'D':
                        case 'd':
                            Console.WriteLine("Closing subscriptions in server");
                            ServerControl?.CloseSubscriptions();
                            break;
                        case '!':
                            var control = ServerControl;
                            if (control != null)
                            {
                                Console.WriteLine("Chaos !!!!!!!!!!!!!...");
                                control.Chaos = !control.Chaos;
                            }
                            break;
                    }
                }

                // Wait for hosting task to exit
                hostingTask.GetAwaiter().GetResult();
            }
            catch (Exception e)
            {
                logger.LogError(e, "Exception");
            }
        }