winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

Argument.cpp (36373B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "Argument.h"
      5 #include "Command.h"
      6 #include "Resources.h"
      7 #include <winget/UserSettings.h>
      8 #include <winget/LocIndependent.h>
      9 
     10 namespace AppInstaller::CLI
     11 {
     12     using namespace AppInstaller::CLI::Execution;
     13     using namespace Settings;
     14     using namespace AppInstaller::Utility::literals;
     15 
     16     namespace
     17     {
     18         bool ContainsArgumentFromList(const Execution::Args& args, const std::vector<Execution::Args::Type>& argTypes)
     19         {
     20             return std::any_of(argTypes.begin(), argTypes.end(), [&](Execution::Args::Type arg) { return args.Contains(arg); });
     21         }
     22     }
     23 
     24     ArgumentCommon ArgumentCommon::ForType(Execution::Args::Type type)
     25     {
     26         // A test ensures that all types are listed here
     27         switch (type)
     28         {
     29         // Args to specify where to get app
     30         case Execution::Args::Type::Query:
     31             return { type, "query"_liv, 'q', ArgTypeCategory::PackageQuery | ArgTypeCategory::SinglePackageQuery };
     32         case Execution::Args::Type::MultiQuery:
     33             return { type, "query"_liv, 'q', ArgTypeCategory::PackageQuery | ArgTypeCategory::MultiplePackages };
     34         case Execution::Args::Type::Manifest:
     35             return { type, "manifest"_liv, 'm', ArgTypeCategory::Manifest };
     36 
     37         // Query filtering criteria and query behavior
     38         case Execution::Args::Type::Id:
     39             return { type, "id"_liv, ArgTypeCategory::PackageQuery | ArgTypeCategory::SinglePackageQuery };
     40         case Execution::Args::Type::Name:
     41             return { type, "name"_liv, ArgTypeCategory::PackageQuery | ArgTypeCategory::SinglePackageQuery };
     42         case Execution::Args::Type::Moniker:
     43             return { type, "moniker"_liv, ArgTypeCategory::PackageQuery | ArgTypeCategory::SinglePackageQuery };
     44         case Execution::Args::Type::Tag:
     45             return { type, "tag"_liv, ArgTypeCategory::PackageQuery };
     46         case Execution::Args::Type::Command:
     47             return { type, "command"_liv, "cmd"_liv, ArgTypeCategory::PackageQuery | ArgTypeCategory::SinglePackageQuery };
     48         case Execution::Args::Type::Source:
     49             return { type, "source"_liv, 's', ArgTypeCategory::QuerySource };
     50         case Execution::Args::Type::Count:
     51             return { type, "count"_liv, 'n', ArgTypeCategory::PackageQuery | ArgTypeCategory::SinglePackageQuery };
     52         case Execution::Args::Type::Exact:
     53             return { type, "exact"_liv, 'e', ArgTypeCategory::PackageQuery };
     54 
     55         // Manifest selection behavior after an app is found
     56         case Execution::Args::Type::Version:
     57             return { type, "version"_liv, 'v', ArgTypeCategory::PackageQuery | ArgTypeCategory::SinglePackageQuery };
     58         case Execution::Args::Type::Channel:
     59             return { type, "channel"_liv, 'c', ArgTypeCategory::PackageQuery };
     60 
     61         // Install behavior
     62         case Execution::Args::Type::Interactive:
     63             return { type, "interactive"_liv, 'i', ArgTypeCategory::InstallerBehavior | ArgTypeCategory::CopyFlagToSubContext };
     64         case Execution::Args::Type::Silent:
     65             return { type, "silent"_liv, 'h', ArgTypeCategory::InstallerBehavior | ArgTypeCategory::CopyFlagToSubContext };
     66         case Execution::Args::Type::Locale:
     67             return { type, "locale"_liv, ArgTypeCategory::InstallerSelection | ArgTypeCategory::CopyValueToSubContext };
     68         case Execution::Args::Type::Log:
     69             return { type, "log"_liv, 'o', ArgTypeCategory::InstallerSelection | ArgTypeCategory::SingleInstallerBehavior };
     70         case Execution::Args::Type::CustomSwitches:
     71             return { type, "custom"_liv, ArgTypeCategory::InstallerSelection | ArgTypeCategory::SingleInstallerBehavior };
     72         case Execution::Args::Type::Override:
     73             return { type, "override"_liv, ArgTypeCategory::InstallerSelection | ArgTypeCategory::SingleInstallerBehavior };
     74         case Execution::Args::Type::InstallLocation:
     75             return { type, "location"_liv, 'l', ArgTypeCategory::InstallerSelection | ArgTypeCategory::SingleInstallerBehavior };
     76         case Execution::Args::Type::InstallScope:
     77             return { type, "scope"_liv, ArgTypeCategory::InstallerSelection | ArgTypeCategory::CopyValueToSubContext };
     78         case Execution::Args::Type::InstallArchitecture:
     79             return { type, "architecture"_liv, 'a', ArgTypeCategory::InstallerSelection | ArgTypeCategory::CopyValueToSubContext };
     80         case Execution::Args::Type::InstallerArchitecture: // Used for input architecture that does not need applicability check. E.g. Download, Show.
     81             return { type, "architecture"_liv, 'a', ArgTypeCategory::InstallerSelection | ArgTypeCategory::CopyValueToSubContext };
     82         case Execution::Args::Type::InstallerType:
     83             return { type, "installer-type"_liv, ArgTypeCategory::InstallerSelection };
     84         case Execution::Args::Type::HashOverride:
     85             return { type, "ignore-security-hash"_liv, ArgTypeCategory::InstallerBehavior | ArgTypeCategory::CopyFlagToSubContext };
     86         case Execution::Args::Type::IgnoreLocalArchiveMalwareScan:
     87             return { type, "ignore-local-archive-malware-scan"_liv, ArgTypeCategory::InstallerBehavior | ArgTypeCategory::CopyFlagToSubContext };
     88         case Execution::Args::Type::AcceptPackageAgreements:
     89             return { type, "accept-package-agreements"_liv, ArgTypeCategory::InstallerBehavior };
     90         case Execution::Args::Type::Rename:
     91             return { type, "rename"_liv, 'r' };
     92         case Execution::Args::Type::NoUpgrade:
     93             return { type, "no-upgrade"_liv, ArgTypeCategory::CopyFlagToSubContext };
     94         case Execution::Args::Type::SkipDependencies:
     95             return { type, "skip-dependencies"_liv, ArgTypeCategory::InstallerBehavior | ArgTypeCategory::CopyFlagToSubContext };
     96         case Execution::Args::Type::AllowReboot:
     97             return { type, "allow-reboot"_liv, ArgTypeCategory::InstallerBehavior | ArgTypeCategory::CopyFlagToSubContext };
     98 
     99         // Uninstall behavior
    100         case Execution::Args::Type::Purge:
    101             return { type, "purge"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::PurgePreserve };
    102         case Execution::Args::Type::Preserve:
    103             return { type, "preserve"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::PurgePreserve };
    104         case Execution::Args::Type::ProductCode:
    105             return { type, "product-code"_liv, ArgTypeCategory::SinglePackageQuery };
    106         case Execution::Args::Type::AllVersions:
    107             return { type, "all-versions"_liv, "all"_liv, ArgTypeCategory::CopyFlagToSubContext, ArgTypeExclusiveSet::AllAndTargetVersion };
    108         case Execution::Args::Type::TargetVersion:
    109             return { type, "version"_liv, 'v', ArgTypeCategory::SinglePackageQuery, ArgTypeExclusiveSet::AllAndTargetVersion };
    110 
    111         //Source Command
    112         case Execution::Args::Type::SourceName:
    113             return { type, "name"_liv, 'n' };
    114         case Execution::Args::Type::SourceType:
    115             return { type, "type"_liv, 't' };
    116         case Execution::Args::Type::SourceArg:
    117             return { type, "arg"_liv, 'a' };
    118         case Execution::Args::Type::ForceSourceReset:
    119             return { type, "force"_liv };
    120         case Execution::Args::Type::SourceExplicit:
    121             return { type, "explicit"_liv };
    122         case Execution::Args::Type::SourceTrustLevel:
    123             return { type, "trust-level"_liv };
    124 
    125         //Hash Command
    126         case Execution::Args::Type::HashFile:
    127             return { type, "file"_liv, 'f' };
    128         case Execution::Args::Type::Msix:
    129             return { type, "msix"_liv, 'm' };
    130 
    131         //Validate Command
    132         case Execution::Args::Type::ValidateManifest:
    133             return { type, "manifest"_liv };
    134         case Execution::Args::Type::IgnoreWarnings:
    135             return { type, "ignore-warnings"_liv, "nowarn"_liv};
    136 
    137         // Complete Command
    138         case Execution::Args::Type::Word:
    139             return { type, "word"_liv };
    140         case Execution::Args::Type::CommandLine:
    141             return { type, "commandline"_liv };
    142         case Execution::Args::Type::Position:
    143             return { type, "position"_liv };
    144 
    145         // Export Command
    146         case Execution::Args::Type::IncludeVersions:
    147             return { type, "include-versions"_liv };
    148 
    149         // Import Command
    150         case Execution::Args::Type::ImportFile:
    151             return { type, "import-file"_liv, 'i' };
    152         case Execution::Args::Type::IgnoreUnavailable:
    153             return { type, "ignore-unavailable"_liv };
    154         case Execution::Args::Type::IgnoreVersions:
    155             return { type, "ignore-versions"_liv };
    156 
    157         // Setting Command
    158         case Execution::Args::Type::AdminSettingEnable:
    159             return { type, "enable"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::EnableDisable };
    160         case Execution::Args::Type::AdminSettingDisable:
    161             return { type, "disable"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::EnableDisable };
    162         case Execution::Args::Type::SettingName:
    163             return { type, "setting"_liv };
    164         case Execution::Args::Type::SettingValue:
    165             return { type, "value"_liv };
    166 
    167         // Upgrade command
    168         case Execution::Args::Type::All:
    169             return { type, "all"_liv, 'r', "recurse"_liv, ArgTypeCategory::MultiplePackages };
    170         case Execution::Args::Type::IncludeUnknown:
    171             return { type, "include-unknown"_liv, 'u', "unknown"_liv, ArgTypeCategory::CopyFlagToSubContext };
    172         case Execution::Args::Type::IncludePinned:
    173             return { type, "include-pinned"_liv, "pinned"_liv, ArgTypeCategory::CopyFlagToSubContext };
    174         case Execution::Args::Type::UninstallPrevious:
    175             return { type, "uninstall-previous"_liv, ArgTypeCategory::InstallerBehavior | ArgTypeCategory::CopyFlagToSubContext };
    176 
    177         // Show command
    178         case Execution::Args::Type::ListVersions:
    179             return { type, "versions"_liv };
    180 
    181         // List command
    182         case Execution::Args::Type::Upgrade:
    183             return { type, "upgrade-available"_liv};
    184 
    185         // Pin command
    186         case Execution::Args::Type::GatedVersion:
    187             return { type, "version"_liv, 'v', ArgTypeCategory::None, ArgTypeExclusiveSet::PinType };
    188         case Execution::Args::Type::BlockingPin:
    189             return { type, "blocking"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::PinType };
    190         case Execution::Args::Type::PinInstalled:
    191             return { type, "installed"_liv, ArgTypeCategory::None };
    192 
    193         // Error command
    194         case Execution::Args::Type::ErrorInput:
    195             return { type, "input"_liv, ArgTypeCategory::None };
    196 
    197         // Resume command
    198         case Execution::Args::Type::ResumeId:
    199             return { type, "resume-id"_liv, 'g', ArgTypeCategory::None };
    200         case Execution::Args::Type::IgnoreResumeLimit:
    201             return { type, "ignore-resume-limit"_liv, ArgTypeCategory::None };
    202 
    203         // Font command
    204         case Execution::Args::Type::Family:
    205             return { type, "family"_liv, ArgTypeCategory::None };
    206 
    207         // Configuration commands
    208         case Execution::Args::Type::ConfigurationFile:
    209             return { type, "file"_liv, 'f', ArgTypeCategory::ConfigurationSetChoice, ArgTypeExclusiveSet::ConfigurationSetChoice };
    210         case Execution::Args::Type::ConfigurationAcceptWarning:
    211             return { type, "accept-configuration-agreements"_liv };
    212         case Execution::Args::Type::ConfigurationSuppressPrologue:
    213             return { type, "suppress-initial-details"_liv };
    214         case Execution::Args::Type::ExtendedFeaturesEnable:
    215             return { type, "enable"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::StubType };
    216         case Execution::Args::Type::ExtendedFeaturesDisable:
    217             return { type, "disable"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::StubType };
    218         case Execution::Args::Type::ConfigurationModulePath:
    219             return { type, "module-path"_liv };
    220         case Execution::Args::Type::ConfigurationProcessorPath:
    221             return { type, "processor-path"_liv };
    222         case Execution::Args::Type::ConfigurationExportPackageId:
    223             return { type, "package-id"_liv };
    224         case Execution::Args::Type::ConfigurationExportModule:
    225             return { type, "module"_liv };
    226         case Execution::Args::Type::ConfigurationExportResource:
    227             return { type, "resource"_liv };
    228         case Execution::Args::Type::ConfigurationExportAll:
    229             return { type, "all"_liv, 'r', "recurse"_liv };
    230         case Execution::Args::Type::ConfigurationHistoryItem:
    231             return { type, "history"_liv, 'h', ArgTypeCategory::ConfigurationSetChoice, ArgTypeExclusiveSet::ConfigurationSetChoice };
    232         case Execution::Args::Type::ConfigurationHistoryRemove:
    233             return { type, "remove"_liv };
    234         case Execution::Args::Type::ConfigurationStatusWatch:
    235             return { type, "live"_liv };
    236 
    237         // DSCv3 resources
    238         case Execution::Args::Type::DscResourceFunctionGet:
    239             return { type, "get"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::DscResourceFunction };
    240         case Execution::Args::Type::DscResourceFunctionSet:
    241             return { type, "set"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::DscResourceFunction };
    242         case Execution::Args::Type::DscResourceFunctionWhatIf:
    243             return { type, "whatIf"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::DscResourceFunction };
    244         case Execution::Args::Type::DscResourceFunctionTest:
    245             return { type, "test"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::DscResourceFunction };
    246         case Execution::Args::Type::DscResourceFunctionDelete:
    247             return { type, "delete"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::DscResourceFunction };
    248         case Execution::Args::Type::DscResourceFunctionExport:
    249             return { type, "export"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::DscResourceFunction };
    250         case Execution::Args::Type::DscResourceFunctionValidate:
    251             return { type, "validate"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::DscResourceFunction };
    252         case Execution::Args::Type::DscResourceFunctionResolve:
    253             return { type, "resolve"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::DscResourceFunction };
    254         case Execution::Args::Type::DscResourceFunctionAdapter:
    255             return { type, "adapter"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::DscResourceFunction };
    256         case Execution::Args::Type::DscResourceFunctionSchema:
    257             return { type, "schema"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::DscResourceFunction };
    258         case Execution::Args::Type::DscResourceFunctionManifest:
    259             return { type, "manifest"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::DscResourceFunction };
    260 
    261         // Download command
    262         case Execution::Args::Type::DownloadDirectory:
    263             return { type, "download-directory"_liv, 'd', ArgTypeCategory::None };
    264         case Execution::Args::Type::Platform:
    265             return { type, "platform"_liv, ArgTypeCategory::None };
    266         case Execution::Args::Type::SkipMicrosoftStorePackageLicense:
    267             return { type, "skip-microsoft-store-package-license"_liv, "skip-license"_liv, ArgTypeCategory::None };
    268         case Execution::Args::Type::OSVersion:
    269             return { type, "os-version"_liv, ArgTypeCategory::None };
    270 
    271         // Common arguments
    272         case Execution::Args::Type::NoVT:
    273             return { type, "no-vt"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::ProgressBarOption };
    274         case Execution::Args::Type::RetroStyle:
    275             return { type, "retro"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::ProgressBarOption };
    276         case Execution::Args::Type::RainbowStyle:
    277             return { type, "rainbow"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::ProgressBarOption };
    278         case Execution::Args::Type::Help:
    279             return { type, "help"_liv, APPINSTALLER_CLI_HELP_ARGUMENT_TEXT_CHAR };
    280         case Execution::Args::Type::Info:
    281             return { type, "info"_liv };
    282         case Execution::Args::Type::VerboseLogs:
    283             return { type, "verbose-logs"_liv, "verbose"_liv };
    284         case Execution::Args::Type::DisableInteractivity:
    285             return { type, "disable-interactivity"_liv };
    286         case Execution::Args::Type::Wait:
    287             return { type, "wait"_liv };
    288         case Execution::Args::Type::OpenLogs:
    289             return { type, "open-logs"_liv, "logs"_liv };
    290         case Execution::Args::Type::Force:
    291             return { type, "force"_liv, ArgTypeCategory::CopyFlagToSubContext };
    292         case Execution::Args::Type::OutputFile:
    293             return { type, "output"_liv, 'o' };
    294         case Execution::Args::Type::Correlation:
    295             return { type, "correlation"_liv };
    296 
    297         case Execution::Args::Type::DependencySource:
    298             return { type, "dependency-source"_liv, ArgTypeCategory::ExtendedSource };
    299         case Execution::Args::Type::CustomHeader:
    300             return { type, "header"_liv, ArgTypeCategory::ExtendedSource };
    301         case Execution::Args::Type::AcceptSourceAgreements:
    302             return { type, "accept-source-agreements"_liv, ArgTypeCategory::ExtendedSource };
    303 
    304         case Execution::Args::Type::Proxy:
    305             return { type, "proxy"_liv, ArgTypeCategory::CopyValueToSubContext, ArgTypeExclusiveSet::Proxy };
    306         case Execution::Args::Type::NoProxy:
    307             return { type, "no-proxy"_liv, ArgTypeCategory::CopyFlagToSubContext, ArgTypeExclusiveSet::Proxy };
    308 
    309         case Execution::Args::Type::ToolVersion:
    310             return { type, "version"_liv, 'v' };
    311 
    312         // Authentication arguments
    313         case Execution::Args::Type::AuthenticationMode:
    314             return { type, "authentication-mode"_liv, ArgTypeCategory::CopyValueToSubContext };
    315         case Execution::Args::Type::AuthenticationAccount:
    316             return { type, "authentication-account"_liv, ArgTypeCategory::CopyValueToSubContext };
    317 
    318         // Used for demonstration purposes
    319         case Execution::Args::Type::ExperimentalArg:
    320                 return { type, "arg"_liv };
    321 
    322         default:
    323             THROW_HR(E_UNEXPECTED);
    324         }
    325     }
    326 
    327     std::vector<ArgumentCommon> ArgumentCommon::GetFromExecArgs(const Execution::Args& execArgs)
    328     {
    329         auto argTypes = execArgs.GetTypes();
    330         std::vector<ArgumentCommon> result;
    331         std::transform(argTypes.begin(), argTypes.end(), std::back_inserter(result), ArgumentCommon::ForType);
    332         return result;
    333     }
    334 
    335     Argument Argument::ForType(Execution::Args::Type type)
    336     {
    337         switch (type)
    338         {
    339         case Args::Type::Query:
    340             return Argument{ type, Resource::String::QueryArgumentDescription, ArgumentType::Positional};
    341         case Args::Type::MultiQuery:
    342             return Argument{ type, Resource::String::MultiQueryArgumentDescription, ArgumentType::Positional }.SetCountLimit(128);
    343         case Args::Type::Manifest:
    344             return Argument{ type, Resource::String::ManifestArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help, Settings::TogglePolicy::Policy::LocalManifestFiles, Settings::BoolAdminSetting::LocalManifestFiles };
    345         case Args::Type::Id:
    346             return Argument{ type, Resource::String::IdArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
    347         case Args::Type::Name:
    348             return Argument{ type, Resource::String::NameArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
    349         case Args::Type::Moniker:
    350             return Argument{ type, Resource::String::MonikerArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
    351         case Args::Type::Tag:
    352             return Argument{ type, Resource::String::TagArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
    353         case Args::Type::Command:
    354             return Argument{ type, Resource::String::CommandArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
    355         case Args::Type::Source:
    356             return Argument{ type, Resource::String::SourceArgumentDescription, ArgumentType::Standard };
    357         case Args::Type::DependencySource:
    358             return Argument{ type, Resource::String::DependencySourceArgumentDescription, ArgumentType::Standard };
    359         case Args::Type::Count:
    360             return Argument{ type, Resource::String::CountArgumentDescription, ArgumentType::Standard };
    361         case Args::Type::Exact:
    362             return Argument{ type, Resource::String::ExactArgumentDescription, ArgumentType::Flag };
    363         case Args::Type::Version:
    364             return Argument{ type, Resource::String::VersionArgumentDescription, ArgumentType::Standard };
    365         case Args::Type::Channel:
    366             return Argument{ type, Resource::String::ChannelArgumentDescription, ArgumentType::Standard, Argument::Visibility::Hidden };
    367         case Args::Type::Interactive:
    368             return Argument{ type, Resource::String::InteractiveArgumentDescription, ArgumentType::Flag };
    369         case Args::Type::Silent:
    370             return Argument{ type, Resource::String::SilentArgumentDescription, ArgumentType::Flag };
    371         case Args::Type::Locale:
    372             return Argument{ type, Resource::String::LocaleArgumentDescription, ArgumentType::Standard };
    373         case Args::Type::InstallArchitecture:
    374             return Argument{ type, Resource::String::ArchitectureArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
    375         case Args::Type::InstallerArchitecture:
    376             return Argument{ type, Resource::String::ArchitectureArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
    377         case Args::Type::Log:
    378             return Argument{ type, Resource::String::LogArgumentDescription, ArgumentType::Standard };
    379         case Args::Type::CustomSwitches:
    380             return Argument{ type, Resource::String::CustomSwitchesArgumentDescription, ArgumentType::Standard };
    381         case Args::Type::Override:
    382             return Argument{ type, Resource::String::OverrideArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
    383         case Args::Type::InstallLocation:
    384             return Argument{ type, Resource::String::LocationArgumentDescription, ArgumentType::Standard };
    385         case Args::Type::HashOverride:
    386             return Argument{ type, Resource::String::HashOverrideArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::HashOverride, Settings::BoolAdminSetting::InstallerHashOverride };
    387         case Args::Type::AcceptPackageAgreements:
    388             return Argument{ type, Resource::String::AcceptPackageAgreementsArgumentDescription, ArgumentType::Flag };
    389         case Args::Type::NoUpgrade:
    390             return Argument{ type, Resource::String::NoUpgradeArgumentDescription, ArgumentType::Flag };
    391         case Args::Type::HashFile:
    392             return Argument{ type, Resource::String::FileArgumentDescription, ArgumentType::Positional, true };
    393         case Args::Type::Msix:
    394             return Argument{ type, Resource::String::MsixArgumentDescription, ArgumentType::Flag };
    395         case Args::Type::ListVersions:
    396             return Argument{ type, Resource::String::VersionsArgumentDescription, ArgumentType::Flag };
    397         case Args::Type::Help:
    398             return Argument{ type, Resource::String::HelpArgumentDescription, ArgumentType::Flag };
    399         case Args::Type::SkipDependencies:
    400             return Argument{ type, Resource::String::SkipDependenciesArgumentDescription, ArgumentType::Flag, false };
    401         case Args::Type::IgnoreLocalArchiveMalwareScan:
    402             return Argument{ type, Resource::String::IgnoreLocalArchiveMalwareScanArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::LocalArchiveMalwareScanOverride, Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride };
    403         case Args::Type::SourceName:
    404             return Argument{ type, Resource::String::SourceNameArgumentDescription, ArgumentType::Positional, false };
    405         case Args::Type::SourceArg:
    406             return Argument{ type, Resource::String::SourceArgArgumentDescription, ArgumentType::Positional, true };
    407         case Args::Type::SourceType:
    408             return Argument{ type, Resource::String::SourceTypeArgumentDescription, ArgumentType::Positional };
    409         case Args::Type::SourceExplicit:
    410             return Argument{ type, Resource::String::SourceExplicitArgumentDescription, ArgumentType::Flag };
    411         case Args::Type::SourceTrustLevel:
    412             return Argument{ type, Resource::String::SourceTrustLevelArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
    413         case Args::Type::ValidateManifest:
    414             return Argument{ type, Resource::String::ValidateManifestArgumentDescription, ArgumentType::Positional, true };
    415         case Args::Type::IgnoreWarnings:
    416             return Argument{ type, Resource::String::IgnoreWarningsArgumentDescription, ArgumentType::Flag, Argument::Visibility::Help };
    417         case Args::Type::NoVT:
    418             return Argument{ type, Resource::String::NoVTArgumentDescription, ArgumentType::Flag, Argument::Visibility::Hidden };
    419         case Args::Type::RainbowStyle:
    420             return Argument{ type, Resource::String::RainbowArgumentDescription, ArgumentType::Flag, Argument::Visibility::Hidden };
    421         case Args::Type::RetroStyle:
    422             return Argument{ type, Resource::String::RetroArgumentDescription, ArgumentType::Flag, Argument::Visibility::Hidden };
    423         case Args::Type::VerboseLogs:
    424             return Argument{ type, Resource::String::VerboseLogsArgumentDescription, ArgumentType::Flag };
    425         case Args::Type::CustomHeader:
    426             return Argument{ type, Resource::String::HeaderArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
    427         case Args::Type::AcceptSourceAgreements:
    428             return Argument{ type, Resource::String::AcceptSourceAgreementsArgumentDescription, ArgumentType::Flag };
    429         case Args::Type::AuthenticationMode:
    430             return Argument{ type, Resource::String::AuthenticationModeArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
    431         case Args::Type::AuthenticationAccount:
    432             return Argument{ type, Resource::String::AuthenticationAccountArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
    433         case Args::Type::ExperimentalArg:
    434             return Argument{ type, Resource::String::ExperimentalArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::ExperimentalArg };
    435         case Args::Type::Rename:
    436             return Argument{ type, Resource::String::RenameArgumentDescription, ArgumentType::Standard, false };
    437         case Args::Type::Purge:
    438             return Argument{ type, Resource::String::PurgeArgumentDescription, ArgumentType::Flag, false };
    439         case Args::Type::Preserve:
    440             return Argument{ type, Resource::String::PreserveArgumentDescription, ArgumentType::Flag, false };
    441         case Args::Type::Wait:
    442             return Argument{ type, Resource::String::WaitArgumentDescription, ArgumentType::Flag, false };
    443         case Args::Type::ProductCode:
    444             return Argument{ type, Resource::String::ProductCodeArgumentDescription, ArgumentType::Standard, false };
    445         case Args::Type::OpenLogs:
    446             return Argument{ type, Resource::String::OpenLogsArgumentDescription, ArgumentType::Flag, Argument::Visibility::Help };
    447         case Args::Type::UninstallPrevious:
    448             return Argument{ type, Resource::String::UninstallPreviousArgumentDescription, ArgumentType::Flag, Argument::Visibility::Help };
    449         case Args::Type::Force:
    450             return Argument{ type, Resource::String::ForceArgumentDescription, ArgumentType::Flag, false };
    451         case Args::Type::DownloadDirectory:
    452             return Argument{ type, Resource::String::DownloadDirectoryArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help, false };
    453         case Args::Type::SkipMicrosoftStorePackageLicense:
    454             return Argument{ type, Resource::String::SkipMicrosoftStorePackageLicenseArgumentDescription, ArgumentType::Flag, Argument::Visibility::Help, false };
    455         case Args::Type::Platform:
    456             return Argument{ type, Resource::String::PlatformArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help, false };
    457         case Args::Type::InstallerType:
    458             return Argument{ type, Resource::String::InstallerTypeArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help, false };
    459         case Args::Type::ResumeId:
    460             return Argument{ type, Resource::String::ResumeIdArgumentDescription, ArgumentType::Standard, true };
    461         case Args::Type::AllowReboot:
    462             return Argument{ type, Resource::String::AllowRebootArgumentDescription, ArgumentType::Flag };
    463         case Args::Type::IgnoreResumeLimit:
    464             return Argument{ type, Resource::String::IgnoreResumeLimitArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Resume };
    465         case Args::Type::AllVersions:
    466             return Argument{ type, Resource::String::UninstallAllVersionsArgumentDescription, ArgumentType::Flag, Argument::Visibility::Help };
    467         case Args::Type::TargetVersion:
    468             return Argument{ type, Resource::String::TargetVersionArgumentDescription, ArgumentType::Standard };
    469         case Args::Type::Proxy:
    470             return Argument{ type, Resource::String::ProxyArgumentDescription, ArgumentType::Standard, TogglePolicy::Policy::ProxyCommandLineOptions, BoolAdminSetting::ProxyCommandLineOptions };
    471         case Args::Type::NoProxy:
    472             return Argument{ type, Resource::String::NoProxyArgumentDescription, ArgumentType::Flag, TogglePolicy::Policy::ProxyCommandLineOptions, BoolAdminSetting::ProxyCommandLineOptions };
    473         case Args::Type::Family:
    474             return Argument{ type, Resource::String::FontFamilyNameArgumentDescription, ArgumentType::Positional, false };
    475         case Args::Type::Correlation:
    476             return Argument{ type, Resource::String::CorrelationArgumentDescription, ArgumentType::Standard, Argument::Visibility::Hidden };
    477         default:
    478             THROW_HR(E_UNEXPECTED);
    479         }
    480     }
    481 
    482     void Argument::GetCommon(std::vector<Argument>& args)
    483     {
    484         args.push_back(ForType(Args::Type::Help));
    485         args.push_back(ForType(Args::Type::Wait));
    486         args.push_back(ForType(Args::Type::OpenLogs));
    487         args.push_back(ForType(Args::Type::NoVT));
    488         args.push_back(ForType(Args::Type::RainbowStyle));
    489         args.push_back(ForType(Args::Type::RetroStyle));
    490         args.push_back(ForType(Args::Type::VerboseLogs));
    491         args.push_back(ForType(Args::Type::IgnoreWarnings));
    492         args.emplace_back(Args::Type::DisableInteractivity, Resource::String::DisableInteractivityArgumentDescription, ArgumentType::Flag, false);
    493         args.push_back(ForType(Args::Type::Proxy));
    494         args.push_back(ForType(Args::Type::NoProxy));
    495         args.push_back(ForType(Args::Type::Correlation));
    496     }
    497 
    498     std::string Argument::GetUsageString() const
    499     {
    500         std::ostringstream strstr;
    501         if (Alias() != ArgumentCommon::NoAlias)
    502         {
    503             strstr << APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_CHAR << Alias() << ',';
    504         }
    505         if (AlternateName() != Argument::NoAlternateName)
    506         {
    507             strstr << APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_CHAR << APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_CHAR << AlternateName() << ',';
    508         }
    509         strstr << APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_CHAR << APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_CHAR << Name();
    510         return strstr.str();
    511     }
    512 
    513     void Argument::ValidateExclusiveArguments(const Execution::Args& args)
    514     {
    515         auto argProperties = ArgumentCommon::GetFromExecArgs(args);
    516 
    517         using ExclusiveSet_t = std::underlying_type_t<ArgTypeExclusiveSet>;
    518         for (ExclusiveSet_t i = 1 + static_cast<ExclusiveSet_t>(ArgTypeExclusiveSet::None); i < static_cast<ExclusiveSet_t>(ArgTypeExclusiveSet::Max); i <<= 1)
    519         {
    520             std::vector<ArgumentCommon> argsFromSet;
    521             std::copy_if(
    522                 argProperties.begin(),
    523                 argProperties.end(),
    524                 std::back_inserter(argsFromSet),
    525                 [=](const ArgumentCommon& arg) { return static_cast<ExclusiveSet_t>(arg.ExclusiveSet) & i; });
    526 
    527             if (argsFromSet.size() > 1)
    528             {
    529                 // Create a string showing the exclusive args.
    530                 std::string argsString;
    531                 for (const auto& arg : argsFromSet)
    532                 {
    533                     if (!argsString.empty())
    534                     {
    535                         argsString += '|';
    536 
    537                     }
    538 
    539                     argsString += arg.Name;
    540                 }
    541 
    542                 throw CommandException(Resource::String::MultipleExclusiveArgumentsProvided(Utility::LocIndString{ argsString }));
    543             }
    544         }
    545     }
    546 
    547     void Argument::ValidateArgumentDependency(const Execution::Args& args, Execution::Args::Type type, Execution::Args::Type dependencyArgType)
    548     {
    549         if (args.Contains(type) && !args.Contains(dependencyArgType))
    550         {
    551             throw CommandException(Resource::String::DependencyArgumentMissing(
    552                 Utility::LocIndString{ ArgumentCommon::ForType(type).Name },
    553                 Utility::LocIndString{ ArgumentCommon::ForType(dependencyArgType).Name }));
    554         }
    555     }
    556 
    557     ArgTypeCategory Argument::GetCategoriesPresent(const Execution::Args& args)
    558     {
    559         auto argProperties = ArgumentCommon::GetFromExecArgs(args);
    560 
    561         ArgTypeCategory result = ArgTypeCategory::None;
    562         for (const auto& arg : argProperties)
    563         {
    564             result |= arg.TypeCategory;
    565         }
    566 
    567         return result;
    568     }
    569 
    570     ArgTypeCategory Argument::GetCategoriesAndValidateCommonArguments(const Execution::Args& args, bool requirePackageSelectionArg)
    571     {
    572         const auto categories = GetCategoriesPresent(args);
    573 
    574         // Commands like install require some argument to select a package
    575         if (requirePackageSelectionArg)
    576         {
    577             if (WI_AreAllFlagsClear(categories, ArgTypeCategory::Manifest | ArgTypeCategory::PackageQuery | ArgTypeCategory::SinglePackageQuery))
    578             {
    579                 throw CommandException(Resource::String::NoPackageSelectionArgumentProvided);
    580             }
    581         }
    582 
    583         // If a manifest is specified, we cannot also have arguments for searching
    584         if (WI_IsFlagSet(categories, ArgTypeCategory::Manifest) &&
    585             WI_IsAnyFlagSet(categories, ArgTypeCategory::PackageQuery | ArgTypeCategory::QuerySource))
    586         {
    587             throw CommandException(Resource::String::BothManifestAndSearchQueryProvided);
    588         }
    589 
    590         // If we have multiple packages, we cannot have arguments that only make sense for a single package
    591         if (WI_IsFlagSet(categories, ArgTypeCategory::MultiplePackages) &&
    592             WI_IsAnyFlagSet(categories, ArgTypeCategory::SinglePackageQuery | ArgTypeCategory::SingleInstallerBehavior))
    593         {
    594             throw CommandException(Resource::String::ArgumentForSinglePackageProvidedWithMultipleQueries);
    595         }
    596 
    597         return categories;
    598     }
    599 
    600     Argument::Visibility Argument::GetVisibility() const
    601     {
    602         if (!ExperimentalFeature::IsEnabled(m_feature))
    603         {
    604             return Argument::Visibility::Hidden;
    605         }
    606 
    607         if (!GroupPolicies().IsEnabled(m_groupPolicy))
    608         {
    609             return Argument::Visibility::Hidden;
    610         }
    611 
    612         return m_visibility;
    613     }
    614 }