private static async Task MainAsync()

in SurfaceDevCenterManager/Program.cs [90:1021]


        private static async Task<ErrorCodes> MainAsync(string[] args)
        {
            ErrorCodes retval = ErrorCodes.SUCCESS;
            bool show_help = false;
            string CreateOption = null;
            bool CommitOption = false;
            string ListOption = null;
            string ProductId = null;
            string SubmissionId = null;
            string ShippingLabelId = null;
            string PublisherId = null;
            string DownloadOption = null;
            string MetadataOption = null;
            string SubmissionPackagePath = null;
            bool WaitOption = false;
            bool WaitForMetaData = false;
            bool CreateMetaData = false;
            bool AudienceOption = false;
            int OverrideServer = 0;
            bool OverrideServerPresent = false;
            string CredentialsOption = null;
            string AADAuthenticationOption = null;
            string TimeoutOption = null;
            uint HttpTimeout = DEFAULT_TIMEOUT;
            bool TranslateOption = false;
            string AnotherPartnerId = null;

            OptionSet p = new OptionSet() {
                { "c|create=",         "Path to json file with configuration to create", v => CreateOption = v },
                { "commit",            "Commit submission with given ID", v => CommitOption = true },
                { "l|list=",           "List a shippinglabel, product, submission or partnersubmission", v => ListOption = v },
                { "u|upload=",         "Upload a package to a specific product and submission", v => SubmissionPackagePath = v },
                { "productid=",        "Specify a specific ProductId", v => ProductId = v },
                { "submissionid=",     "Specify a specific SubmissionId", v => SubmissionId = v },
                { "shippinglabelid=",  "Specify a specific ShippingLabelId", v => ShippingLabelId = v },
                { "publisherid=",      "Specify a specific PublisherId", v => PublisherId = v },
                { "partnerid=",        "Specify PublisherId of the Partner to share the submission to via shipping label instead of Windows Update", v => AnotherPartnerId = v },
                { "v",                 "Increase debug message verbosity", v => { if (v != null) {++verbosity; }} },
                { "d|download=",       "Download a submission to current directory or folder specified", v => DownloadOption = v ?? Environment.CurrentDirectory },
                { "m|metadata=",       "Download a submission metadata to current directory or folder specified", v => MetadataOption = v ?? Environment.CurrentDirectory },
                { "h|help",            "Show this message and exit", v => show_help = v != null },
                { "w|wait",            "Wait for submission id to be done", v => WaitOption = true },
                { "waitmetadata",      "Wait for metadata to be done as well in a submission", v => WaitForMetaData = true },
                { "createmetadata",    "Requeset metadata creation for older submissions", v => CreateMetaData = true },
                { "a|audience",        "List Audiences", v => AudienceOption = true },
                { "server=",           "Specify target DevCenter server from CredSelect enum", v => { OverrideServer = int.Parse(v); OverrideServerPresent = true; }    },
                { "creds=",            "Option to specify app credentials.  Options: ENVOnly, FileOnly, AADOnly, AADThenFile (Default)", v => CredentialsOption = v },
                { "aad=",              "Option to specify AAD auth behavior.  Options: Never (Default), Prompt, Always, RefreshSession, SelectAccount", v => AADAuthenticationOption = v },
                { "t|timeout=",        $"Adjust the timeout for HTTP requests to specified seconds.  Default:{DEFAULT_TIMEOUT} seconds", v => TimeoutOption = v  },
                { "translate",         "Translate the given publisherid, productid and submissionid from a partner to the values visible in your HDC account", v => TranslateOption = true},
                { "?",                 "Show this message and exit", v => show_help = v != null },
            };

            Console.WriteLine("SurfaceDevCenterManager v" + Assembly.GetExecutingAssembly().GetName().Version);

            List<string> extra;
            try
            {
                extra = p.Parse(args);
            }
            catch (OptionException e)
            {
                ErrorParsingOptions(e.Message);
                Console.WriteLine("Try running with just '--help' for more information.");
                return ErrorCodes.COMMAND_LINE_OPTION_PARSING_FAILED;
            }

            if (show_help)
            {
                ShowHelp(p);
                return ErrorCodes.SUCCESS;
            }

            List<AuthorizationHandlerCredentials> myCreds = await DevCenterCredentialsHandler.GetApiCreds(CredentialsOption, AADAuthenticationOption);

            if (myCreds == null)
            {
                ErrorParsingOptions("Unable to get Dev Center Credentials");
                return ErrorCodes.NO_DEV_CENTER_CREDENTIALS_FOUND;
            }

            if (OverrideServer < 0 || OverrideServer >= myCreds.Count)
            {
                ErrorParsingOptions("OverrideServer invalid - " + OverrideServer);
                return ErrorCodes.OVERRIDE_SERVER_INVALID;
            }
            else
            {
                if (!OverrideServerPresent)
                {
                    string loopServersString = ConfigurationManager.AppSettings["loopservers"];
                    if (loopServersString != null)
                    {
                        string[] serversList = loopServersString.Split(',');
                        int x = (new Random()).Next(0, serversList.Length);
                        OverrideServer = int.Parse(serversList[x]);
                    }
                }
            }

            if (CreateOption != null && (!File.Exists(CreateOption)))
            {
                ErrorParsingOptions("CreateOption invalid - " + CreateOption);
                return ErrorCodes.CREATE_INPUT_FILE_DOES_NOT_EXIST;
            }

            DevCenterHWSubmissionType ListOptionEnum = DevCenterHWSubmissionTypeCheck(ListOption);
            if (ListOption != null && ListOptionEnum == DevCenterHWSubmissionType.Invalid)
            {
                ErrorParsingOptions("ListOption invalid - " + ListOption);
                return ErrorCodes.LIST_INVALID_OPTION;
            }

            if (TimeoutOption != null)
            {
                if (uint.TryParse(TimeoutOption, out uint inputParse))
                {
                    HttpTimeout = inputParse;
                    Console.WriteLine($"> HttpTimeout: {HttpTimeout} seconds");
                }
                else
                {
                    Console.WriteLine($"> HttpTimeout: Invalid value {TimeoutOption}, using default timeout");
                }
            }

            DevCenterOptions options = new DevCenterOptions() { CorrelationId = CorrelationId, HttpTimeoutSeconds = HttpTimeout, RequestDelayMs = 250, LastCommand = LastCommandSet };
            DevCenterHandler api = new DevCenterHandler(myCreds[OverrideServer], options);

            if (CreateOption != null)
            {
                Console.WriteLine("> Create Option");

                CreateInput createInput = JsonConvert.DeserializeObject<CreateInput>(File.ReadAllText(CreateOption));

                if (DevCenterHWSubmissionType.Product == createInput.CreateType)
                {
                    DevCenterResponse<Product> ret = await api.NewProduct(createInput.CreateProduct);
                    if (ret.Error != null)
                    {
                        if (ret.Error.HttpErrorCode == 429)
                        {
                            Console.WriteLine($"{ nameof(CreateOption) } { nameof(api.NewProduct) } experienced a HTTP 429 Too Many Requests response.");
                            return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                        }
                        else
                        {
                            DevCenterErrorDetailsDump(ret.Error);
                            return ErrorCodes.NEW_PRODUCT_API_FAILED;
                        }
                    }
                    else
                    {
                        ret.ReturnValue[0].Dump();
                    }

                }
                else if (DevCenterHWSubmissionType.Submission == createInput.CreateType)
                {
                    if (ProductId == null)
                    {
                        Console.WriteLine("> ERROR: productid not specified");
                        retval = ErrorCodes.NEW_SUBMISSION_PRODUCT_ID_MISSING;
                    }

                    if (retval == 0)
                    {
                        Console.WriteLine("> Creating Submission");
                        DevCenterResponse<Submission> ret = await api.NewSubmission(ProductId, createInput.CreateSubmission);
                        if (ret.Error != null)
                        {
                            if (ret.Error.HttpErrorCode == 429)
                            {
                                Console.WriteLine($"{ nameof(CreateOption) } { nameof(api.NewSubmission) } experienced a HTTP 429 Too Many Requests response.");
                                return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                            }
                            else
                            {
                                DevCenterErrorDetailsDump(ret.Error);
                                return ErrorCodes.NEW_SUBMISSION_API_FAILED;
                            }
                        }
                        else
                        {
                            ret.ReturnValue[0].Dump();
                        }
                    }
                }
                else if (DevCenterHWSubmissionType.ShippingLabel == createInput.CreateType)
                {
                    if (ProductId == null)
                    {
                        Console.WriteLine("> ERROR: productid not specified");
                        retval = ErrorCodes.NEW_SHIPPING_LABEL_PRODUCT_ID_MISSING;
                    }

                    if (SubmissionId == null)
                    {
                        Console.WriteLine("> ERROR: submissionid not specified");
                        retval = ErrorCodes.NEW_SHIPPING_LABEL_SUBMISSION_ID_MISSING;
                    }

                    if (retval == 0)
                    {
                        Console.WriteLine("> Get Driver Metadata");
                        string tmpfile = System.IO.Path.GetTempFileName();

                        DevCenterResponse<Submission> retSubmission = await api.GetSubmission(ProductId, SubmissionId);
                        if (retSubmission.Error != null)
                        {
                            if (retSubmission.Error.HttpErrorCode == 429)
                            {
                                Console.WriteLine($"{ nameof(CreateOption) } { nameof(api.GetSubmission) } experienced a HTTP 429 Too Many Requests response.");
                                return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                            }
                            else
                            {
                                DevCenterErrorDetailsDump(retSubmission.Error);
                                return ErrorCodes.NEW_SHIPPING_LABEL_GET_SUBMISSION_API_FAILED;
                            }
                        }

                        List<Submission> submissions = retSubmission.ReturnValue;
                        List<Download.Item> dls = submissions[0].Downloads.Items;
                        foreach (Download.Item dl in dls)
                        {
                            if (dl.Type.ToLower() == Download.Type.driverMetadata.ToString().ToLower())
                            {
                                Console.WriteLine("> driverMetadata Url: " + dl.Url);
                                BlobStorageHandler bsh = new BlobStorageHandler(dl.Url.AbsoluteUri);
                                await bsh.Download(tmpfile);
                            }
                        }

                        string jsonContent = System.IO.File.ReadAllText(tmpfile);
                        DriverMetadata metadata = JsonConvert.DeserializeObject<DriverMetadata>(jsonContent);
                        System.IO.File.Delete(tmpfile);

                        List<HardwareId> labelHwids = new List<HardwareId>();

                        foreach (KeyValuePair<string, DriverMetadataDetails> bundleInfo in metadata.BundleInfoMap)
                        {
                            foreach (KeyValuePair<string, DriverMetadataInfDetails> infInfo in bundleInfo.Value.InfInfoMap)
                            {
                                foreach (KeyValuePair<string, Dictionary<string, DriverMetadataHWID>> osPnpInfo in infInfo.Value.OSPnPInfoMap)
                                {
                                    foreach (KeyValuePair<string, DriverMetadataHWID> pnpInfo in osPnpInfo.Value)
                                    {
                                        HardwareId labelHwid = new HardwareId
                                        {
                                            BundleId = bundleInfo.Key,
                                            InfId = infInfo.Key,
                                            OperatingSystemCode = osPnpInfo.Key,
                                            PnpString = pnpInfo.Key.ToLower()   // Recommendation from HDC team
                                        };
                                        labelHwids.Add(labelHwid);
                                    }
                                }
                            }
                        }

                        createInput.CreateShippingLabel.Targeting.HardwareIds = labelHwids;
                        createInput.CreateShippingLabel.PublishingSpecifications.GoLiveDate = DateTime.Now.AddDays(7);

                        if (AnotherPartnerId != null)
                        {
                            Console.WriteLine("> Shipping to Partner (not Windows Update): " + AnotherPartnerId);
                            createInput.CreateShippingLabel.Destination = "anotherPartner";
                            createInput.CreateShippingLabel.RecipientSpecifications = new RecipientSpecifications()
                            {
                                EnforceChidTargeting = false,
                                ReceiverPublisherId = AnotherPartnerId
                            };
                        }

                        Console.WriteLine("> Creating Shipping Label");
                        DevCenterResponse<ShippingLabel> ret = await api.NewShippingLabel(ProductId, SubmissionId, createInput.CreateShippingLabel);
                        if (ret.Error != null)
                        {
                            if (ret.Error.HttpErrorCode == 429)
                            {
                                Console.WriteLine($"{ nameof(CreateOption) } { nameof(api.NewShippingLabel) } experienced a HTTP 429 Too Many Requests response.");
                                return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                            }
                            else
                            {
                                DevCenterErrorDetailsDump(ret.Error);
                                return ErrorCodes.NEW_SHIPPING_LABEL_CREATE_API_FAILED;
                            }
                        }
                        else
                        {
                            ret.ReturnValue[0].Dump();
                        }
                    }
                }
                else
                {
                    Console.WriteLine(">  Invalid Create Option selected");
                }
            }
            else if (CommitOption)
            {
                Console.WriteLine("> Commit Option");

                if (ProductId == null)
                {
                    Console.WriteLine("> ERROR: productid not specified");
                    retval = ErrorCodes.COMMIT_PRODUCT_ID_MISSING;
                }

                if (SubmissionId == null)
                {
                    Console.WriteLine("> ERROR: submissionid not specified");
                    retval = ErrorCodes.COMMIT_SUBMISSION_ID_MISSING;
                }

                if (retval == 0)
                {
                    Console.WriteLine("> Sending Commit");

                    DevCenterResponse<bool> ret = await api.CommitSubmission(ProductId, SubmissionId);
                    if (ret.Error != null)
                    {
                        if (ret.Error.HttpErrorCode == 429)
                        {
                            Console.WriteLine($"{ nameof(CommitOption) } { nameof(api.CommitSubmission) } experienced a HTTP 429 Too Many Requests response.");
                            return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                        }
                        else
                        {
                            DevCenterErrorDetailsDump(ret.Error);
                            return ErrorCodes.COMMIT_API_FAILED;
                        }
                    }
                    else
                    {
                        if (!ret.ReturnValue[0])
                        {
                            Console.WriteLine("> Commit Failed");
                            retval = ErrorCodes.COMMIT_API_FAILED;
                        }
                        else
                        {
                            Console.WriteLine("> Commit OK");
                        }

                    }
                }
            }
            else if (ListOption != null)
            {
                Console.WriteLine("> List Option {0}", ListOption);

                switch (ListOptionEnum)
                {
                    case DevCenterHWSubmissionType.Product:
                        {
                            DevCenterResponse<Product> ret = await api.GetProducts(ProductId);
                            if (ret.Error != null)
                            {
                                if (ret.Error.HttpErrorCode == 429)
                                {
                                    Console.WriteLine($"{ nameof(ListOption) } { nameof(api.GetProducts) } experienced a HTTP 429 Too Many Requests response.");
                                    return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                                }
                                else
                                {
                                    DevCenterErrorDetailsDump(ret.Error);
                                    return ErrorCodes.LIST_GET_PRODUCTS_API_FAILED;
                                }
                            }
                            else
                            {
                                List<Product> products = ret.ReturnValue;
                                foreach (Product product in products)
                                {
                                    product.Dump();
                                }
                            }
                        }
                        break;
                    case DevCenterHWSubmissionType.Submission:
                        {
                            DevCenterResponse<Submission> ret = await api.GetSubmission(ProductId, SubmissionId);
                            if (ret.Error != null)
                            {
                                if (ret.Error.HttpErrorCode == 429)
                                {
                                    Console.WriteLine($"{ nameof(ListOption) } { nameof(api.GetSubmission) } experienced a HTTP 429 Too Many Requests response.");
                                    return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                                }
                                else
                                {
                                    DevCenterErrorDetailsDump(ret.Error);
                                    return ErrorCodes.LIST_GET_SUBMISSION_API_FAILED;
                                }
                            }
                            else
                            {
                                List<Submission> submissions = ret.ReturnValue;
                                foreach (Submission submission in submissions)
                                {
                                    submission.Dump();
                                }
                            }
                        }
                        break;
                    case DevCenterHWSubmissionType.ShippingLabel:
                        {
                            DevCenterResponse<ShippingLabel> ret = await api.GetShippingLabels(ProductId, SubmissionId, ShippingLabelId);
                            if (ret.Error != null)
                            {
                                if (ret.Error.HttpErrorCode == 429)
                                {
                                    Console.WriteLine($"{ nameof(ListOption) } { nameof(api.GetShippingLabels) } experienced a HTTP 429 Too Many Requests response.");
                                    return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                                }
                                else
                                {
                                    DevCenterErrorDetailsDump(ret.Error);
                                    return ErrorCodes.LIST_GET_SHIPPING_LABEL_API_FAILED;
                                }
                            }
                            else
                            {
                                List<ShippingLabel> shippingLabels = ret.ReturnValue;
                                foreach (ShippingLabel shippingLabel in shippingLabels)
                                {
                                    shippingLabel.Dump();
                                }
                            }
                        }
                        break;
                    case DevCenterHWSubmissionType.PartnerSubmission:
                        {
                            DevCenterResponse<Submission> ret = await api.GetPartnerSubmission(PublisherId, ProductId, SubmissionId);
                            if (ret.Error != null)
                            {
                                if (ret.Error.HttpErrorCode == 429)
                                {
                                    Console.WriteLine($"{ nameof(ListOption) } { nameof(api.GetPartnerSubmission) } experienced a HTTP 429 Too Many Requests response.");
                                    return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                                }
                                else
                                {
                                    DevCenterErrorDetailsDump(ret.Error);
                                    return ErrorCodes.LIST_GET_PARTNER_SUBMISSION_API_FAILED;
                                }
                            }
                            else
                            {
                                List<Submission> submissions = ret.ReturnValue;
                                foreach (Submission submission in submissions)
                                {
                                    submission.Dump();
                                }
                            }
                        }
                        break;
                    default:
                        Console.WriteLine(">  Invalid List Option selected");
                        break;
                }
            }
            else if (DownloadOption != null)
            {
                Console.WriteLine("> Download Option {0}", DownloadOption);

                string pathNameFull = System.IO.Path.GetFullPath(DownloadOption);
                string FileNamePart = System.IO.Path.GetFileName(DownloadOption);
                string PathNamePart = System.IO.Path.GetDirectoryName(DownloadOption);

                if (!System.IO.Directory.Exists(PathNamePart))
                {
                    Console.WriteLine("> ERROR: Output path does not exist: " + PathNamePart);
                    retval = ErrorCodes.DOWNLOAD_OUTPUT_PATH_NOT_EXIST;
                }

                if (System.IO.File.Exists(DownloadOption))
                {
                    Console.WriteLine("> ERROR: Output file exists already: " + DownloadOption);
                    retval = ErrorCodes.DOWNLOAD_OUTPUT_FILE_ALREADY_EXISTS;
                }

                if (ProductId == null)
                {
                    Console.WriteLine("> ERROR: productid not specified");
                    retval = ErrorCodes.DOWNLOAD_PRODUCT_ID_MISSING;
                }

                if (SubmissionId == null)
                {
                    Console.WriteLine("> ERROR: submissionid not specified");
                    retval = ErrorCodes.DOWNLOAD_SUBMISSION_ID_MISSING;
                }

                if (retval == 0)
                {
                    Console.WriteLine("> Fetch Submission Info");
                    DevCenterResponse<Submission> ret = await api.GetSubmission(ProductId, SubmissionId);
                    if (ret.Error != null)
                    {
                        if (ret.Error.HttpErrorCode == 429)
                        {
                            Console.WriteLine($"{ nameof(DownloadOption) } { nameof(api.GetSubmission) } experienced a HTTP 429 Too Many Requests response.");
                            return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                        }
                        else
                        {
                            DevCenterErrorDetailsDump(ret.Error);
                            return ErrorCodes.DOWNLOAD_GET_SUBMISSION_API_FAILED;
                        }
                    }
                    List<Submission> submissions = ret.ReturnValue;
                    List<Download.Item> dls = submissions[0].Downloads.Items;
                    foreach (Download.Item dl in dls)
                    {
                        if (dl.Type.ToLower() == Download.Type.signedPackage.ToString().ToLower())
                        {
                            Console.WriteLine("> signedPackage Url: " + dl.Url);
                            BlobStorageHandler bsh = new BlobStorageHandler(dl.Url.AbsoluteUri);
                            await bsh.Download(DownloadOption);
                        }
                    }
                }
            }
            else if (MetadataOption != null)
            {
                Console.WriteLine("> Metadata Download Option {0}", MetadataOption);

                if (ProductId == null)
                {
                    Console.WriteLine("> ERROR: productid not specified");
                    retval = ErrorCodes.METADATA_PRODUCT_ID_MISSING;
                }

                if (SubmissionId == null)
                {
                    Console.WriteLine("> ERROR: submissionid not specified");
                    retval = ErrorCodes.METADATA_SUBMISSION_ID_MISSING;
                }

                if (retval == 0)
                {
                    Console.WriteLine("> Fetch Submission Info");
                    DevCenterResponse<Submission> ret = await api.GetSubmission(ProductId, SubmissionId);
                    if (ret.Error != null)
                    {
                        if (ret.Error.HttpErrorCode == 429)
                        {
                            Console.WriteLine($"{ nameof(MetadataOption) } { nameof(api.GetSubmission) } experienced a HTTP 429 Too Many Requests response.");
                            return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                        }
                        else
                        {
                            DevCenterErrorDetailsDump(ret.Error);
                            return ErrorCodes.METADATA_GET_SUBMISSION_API_FAILED;
                        }
                    }
                    List<Submission> submissions = ret.ReturnValue;
                    List<Download.Item> dls = submissions[0].Downloads.Items;
                    bool foundMetaData = false;
                    foreach (Download.Item dl in dls)
                    {
                        if (dl.Type.ToLower() == Download.Type.driverMetadata.ToString().ToLower())
                        {
                            Console.WriteLine("> driverMetadata Url: " + dl.Url);
                            BlobStorageHandler bsh = new BlobStorageHandler(dl.Url.AbsoluteUri);
                            await bsh.Download(MetadataOption);
                            foundMetaData = true;
                        }
                    }

                    if (!foundMetaData)
                    {
                        Console.WriteLine("> ERROR: No Metadata available for this submission");
                    }
                }
            }
            else if (SubmissionPackagePath != null)
            {
                Console.WriteLine("> Upload Option");

                if (ProductId == null)
                {
                    Console.WriteLine("> ERROR: productid not specified");
                    retval = ErrorCodes.UPLOAD_PRODUCT_ID_MISSING;
                }

                if (SubmissionId == null)
                {
                    Console.WriteLine("> ERROR: submissionid not specified");
                    retval = ErrorCodes.UPLOAD_SUBMISSION_ID_MISSING;
                }

                if (retval == 0)
                {
                    Console.WriteLine("> Fetch Submission Info");
                    DevCenterResponse<Submission> ret = await api.GetSubmission(ProductId, SubmissionId);
                    if (ret.Error != null)
                    {
                        if (ret.Error.HttpErrorCode == 429)
                        {
                            Console.WriteLine($"{ nameof(SubmissionPackagePath) } { nameof(api.GetSubmission) } experienced a HTTP 429 Too Many Requests response.");
                            return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                        }
                        else
                        {
                            DevCenterErrorDetailsDump(ret.Error);
                            return ErrorCodes.UPLOAD_GET_SUBMISSION_API_FAILED;
                        }
                    }
                    List<Submission> submissions = ret.ReturnValue;
                    List<Download.Item> dls = submissions[0].Downloads.Items;
                    foreach (Download.Item dl in dls)
                    {
                        if (dl.Type.ToLower() == Download.Type.initialPackage.ToString().ToLower())
                        {
                            Console.WriteLine("> initialPackage Url: " + dl.Url);
                            Console.WriteLine("> Uploading Submission Package");
                            BlobStorageHandler bsh = new BlobStorageHandler(dl.Url.AbsoluteUri);
                            await bsh.Upload(SubmissionPackagePath);
                        }
                    }
                }
            }
            else if (WaitOption)
            {
                Console.WriteLine("> Wait Option");

                if (ProductId == null)
                {
                    Console.WriteLine("> ERROR: productid not specified");
                    retval = ErrorCodes.WAIT_PRODUCT_ID_MISSING;
                }

                if (SubmissionId == null)
                {
                    Console.WriteLine("> ERROR: submissionid not specified");
                    retval = ErrorCodes.WAIT_SUBMISSION_ID_MISSING;
                }

                if (retval == 0)
                {
                    bool done = false;
                    string lastCurrentStep = "";
                    string lastState = "";

                    while (!done)
                    {
                        if (ShippingLabelId == null)
                        {
                            DevCenterResponse<Submission> ret = await api.GetSubmission(ProductId, SubmissionId);
                            if (ret.Error != null)
                            {
                                if (ret.Error.HttpErrorCode == 429)
                                {
                                    Console.WriteLine($"{ nameof(WaitOption) } { nameof(api.GetSubmission) } experienced a HTTP 429 Too Many Requests response.");
                                    await Task.Delay(5000);
                                    continue;
                                }
                                else
                                {
                                    DevCenterErrorDetailsDump(ret.Error);
                                    done = true;
                                    retval = ErrorCodes.WAIT_GET_SUBMISSION_API_FAILED;
                                    break;
                                }
                            }
                            List<Submission> submissions = ret.ReturnValue;
                            Submission sub = submissions[0];

                            if (!done)
                            {
                                if (sub.WorkflowStatus == null)
                                {
                                    Console.WriteLine($"{ nameof(WaitOption) } { sub.Name } { nameof(WorkflowStatus) } was NULL.");
                                    Console.WriteLine($"Please view submission in Partner Center for possible errors. Contact Partner Center support for more information");
                                    Console.WriteLine("WorkflowStatus documentation can be found here : https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/get-product-data#workflow-status-object");
                                    Console.WriteLine("");

                                    done = true;
                                    retval = ErrorCodes.WAIT_GET_SUBMISSION_API_FAILED;
                                    break;
                                }

                                if (sub.WorkflowStatus.CurrentStep != lastCurrentStep ||
                                sub.WorkflowStatus.State != lastState)
                                {
                                    lastCurrentStep = sub.WorkflowStatus.CurrentStep;
                                    lastState = sub.WorkflowStatus.State;
                                    await sub.WorkflowStatus.Dump();
                                }

                                bool haveMetadata = false;
                                bool haveSignedPackage = false;
                                if (sub.Downloads != null)
                                {
                                    List<Download.Item> dls = sub.Downloads.Items;
                                    foreach (Download.Item dl in dls)
                                    {
                                        if (dl.Type.ToLower() == Download.Type.driverMetadata.ToString().ToLower())
                                        {
                                            Console.WriteLine("> driverMetadata Url: " + dl.Url);
                                            haveMetadata = true;
                                        }
                                        if (dl.Type.ToLower() == Download.Type.signedPackage.ToString().ToLower())
                                        {
                                            Console.WriteLine("> signedPackage Url: " + dl.Url);
                                            haveSignedPackage = true;
                                        }
                                    }
                                }

                                if (lastState == "failed")
                                {
                                    done = true;
                                    retval = ErrorCodes.WAIT_SUBMISSION_FAILED_IN_HWDC;
                                }
                                else if (haveSignedPackage)
                                {
                                    if (WaitForMetaData)
                                    {
                                        if (haveMetadata)
                                        {
                                            done = true;
                                            Console.WriteLine("> Submission Ready with Metadata");
                                        }
                                    }
                                    else
                                    {
                                        done = true;
                                        Console.WriteLine("> Submission Ready");
                                    }
                                }

                                if (!done)
                                {
                                    await Task.Delay(5000);
                                }
                            }
                            else
                            {
                                Console.WriteLine("> Signed Package Ready");
                            }
                        }
                        else
                        {
                            DevCenterResponse<ShippingLabel> ret = await api.GetShippingLabels(ProductId, SubmissionId, ShippingLabelId);
                            if (ret.Error != null)
                            {
                                if (ret.Error.HttpErrorCode == 429)
                                {
                                    Console.WriteLine($"{ nameof(WaitOption) } { nameof(api.GetShippingLabels) } experienced a HTTP 429 Too Many Requests response.");
                                    await Task.Delay(5000);
                                    continue;
                                }
                                else
                                {

                                    DevCenterErrorDetailsDump(ret.Error);
                                    done = true;
                                    retval = ErrorCodes.WAIT_GET_SHIPPING_LABEL_API_FAILED;
                                    break;
                                }
                            }
                            List<ShippingLabel> shippingLabels = ret.ReturnValue;
                            ShippingLabel label = shippingLabels[0];

                            if (label.WorkflowStatus.CurrentStep != lastCurrentStep ||
                                label.WorkflowStatus.State != lastState)
                            {
                                lastCurrentStep = label.WorkflowStatus.CurrentStep;
                                lastState = label.WorkflowStatus.State;
                                await label.WorkflowStatus.Dump();
                            }

                            if (lastState == "failed")
                            {
                                done = true;
                                retval = ErrorCodes.WAIT_SHIPPING_LABEL_FAILED_IN_HWDC;
                            }
                            else if (lastCurrentStep == "microsoftApproval")
                            {
                                done = true;
                                Console.WriteLine("> Shipping Label Ready");
                            }
                            else if (lastCurrentStep == "finalizeSharing" && lastState == "completed")
                            {
                                done = true;
                                Console.WriteLine("> Shipping Label for Sharing Ready");
                            }
                            else
                            {
                                await Task.Delay(5000);
                            }
                        }
                    }
                    Console.WriteLine("> Done");
                }
            }
            else if (AudienceOption)
            {
                Console.WriteLine("> Audience Option");

                DevCenterResponse<Audience> ret = await api.GetAudiences();
                if (ret.Error != null)
                {
                    if (ret.Error.HttpErrorCode == 429)
                    {
                        Console.WriteLine($"{ nameof(AudienceOption) } { nameof(api.GetAudiences) } experienced a HTTP 429 Too Many Requests response.");
                        return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                    }
                    else
                    {
                        DevCenterErrorDetailsDump(ret.Error);
                        return ErrorCodes.AUIDENCE_GET_AUDIENCE_API_FAILED;
                    }
                }
                else
                {
                    List<Audience> audiences = ret.ReturnValue;
                    foreach (Audience audience in audiences)
                    {
                        audience.Dump();
                    }
                }
            }
            else if (CreateMetaData)
            {
                Console.WriteLine("> Create MetaData Option");

                if (ProductId == null)
                {
                    Console.WriteLine("> ERROR: productid not specified");
                    retval = ErrorCodes.CREATEMETADATA_PRODUCT_ID_MISSING;
                }

                if (SubmissionId == null)
                {
                    Console.WriteLine("> ERROR: submissionid not specified");
                    retval = ErrorCodes.CREATEMETADATA_SUBMISSION_ID_MISSING;
                }

                if (retval == 0)
                {
                    Console.WriteLine("> Sending Create MetaData");
                    DevCenterResponse<bool> ret = await api.CreateMetaData(ProductId, SubmissionId);
                    if (ret.Error != null)
                    {
                        if (ret.Error.HttpErrorCode == 429)
                        {
                            Console.WriteLine($"{ nameof(CreateMetaData) } { nameof(api.CreateMetaData) } experienced a HTTP 429 Too Many Requests response.");
                            return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                        }
                        else
                        {
                            DevCenterErrorDetailsDump(ret.Error);
                            return ErrorCodes.CREATEMETADATA_API_FAILED;
                        }
                    }
                    else
                    {
                        if (!ret.ReturnValue[0])
                        {
                            Console.WriteLine("> Create MetaData Failed");
                            retval = ErrorCodes.CREATEMETADATA_API_FAILED;
                        }
                        else
                        {
                            Console.WriteLine("> Create MetaData OK");
                        }
                    }
                }
            }
            else if (TranslateOption)
            {
                Console.WriteLine("> Translate Option");

                if (PublisherId == null)
                {
                    Console.WriteLine("> ERROR: publisherid not specified");
                    retval = ErrorCodes.TRANSLATE_PUBLISHER_ID_MISSING;
                }

                if (ProductId == null)
                {
                    Console.WriteLine("> ERROR: productid not specified");
                    retval = ErrorCodes.TRANSLATE_PRODUCT_ID_MISSING;
                }

                if (SubmissionId == null)
                {
                    Console.WriteLine("> ERROR: submissionid not specified");
                    retval = ErrorCodes.TRANSLATE_SUBMISSION_ID_MISSING;
                }

                if (retval == 0)
                {
                    Console.WriteLine("> Requesting Translation");
                    DevCenterResponse<Submission> ret = await api.GetPartnerSubmission(PublisherId, ProductId, SubmissionId);
                    if (ret.Error != null)
                    {
                        if (ret.Error.HttpErrorCode == 429)
                        {
                            Console.WriteLine($"{ nameof(TranslateOption) } { nameof(api.GetPartnerSubmission) } experienced a HTTP 429 Too Many Requests response.");
                            return ErrorCodes.HTTP_429_RATE_LIMIT_EXCEEDED;
                        }
                        else
                        {
                            DevCenterErrorDetailsDump(ret.Error);
                            return ErrorCodes.TRANSLATE_API_FAILED;
                        }
                    }
                    else
                    {
                        if (ret.ReturnValue.Count == 0)
                        {
                            Console.WriteLine("> Translate Failed");
                            retval = ErrorCodes.TRANSLATE_API_FAILED;
                        }
                        else
                        {
                            Console.WriteLine("> Translate OK");
                            ret.ReturnValue[0].Dump();
                        }
                    }
                }
            }
            return retval;
        }