winget-cli

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

SettingsFlow.cpp (7765B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "Resources.h"
      5 #include "SettingsFlow.h"
      6 #include <AppInstallerStrings.h>
      7 #include <winget/UserSettings.h>
      8 #include <winget/AdminSettings.h>
      9 
     10 namespace AppInstaller::CLI::Workflow
     11 {
     12     using namespace AppInstaller::Settings;
     13     using namespace AppInstaller::Utility;
     14 
     15     namespace
     16     {
     17         struct ExportSettingsJson
     18         {
     19             ExportSettingsJson()
     20             {
     21                 root["$schema"] = "https://aka.ms/winget-settings-export.schema.json";
     22                 root["adminSettings"] = Json::ValueType::objectValue;
     23                 root["userSettingsFile"] = UserSettings::SettingsFilePath().u8string();
     24             }
     25 
     26             void AddAdminSetting(BoolAdminSetting setting)
     27             {
     28                 auto str = std::string{ Settings::AdminSettingToString(setting) };
     29                 root["adminSettings"][str] = Settings::IsAdminSettingEnabled(setting);
     30             }
     31 
     32             void AddAdminSetting(StringAdminSetting setting)
     33             {
     34                 auto name = std::string{ Settings::AdminSettingToString(setting) };
     35                 auto value = Settings::GetAdminSetting(setting);
     36                 if (value)
     37                 {
     38                     root["adminSettings"][name] = value.value();
     39                 }
     40             }
     41 
     42             std::string ToJsonString() const
     43             {
     44                 Json::StreamWriterBuilder writerBuilder;
     45                 writerBuilder.settings_["indentation"] = "";
     46                 return Json::writeString(writerBuilder, root);
     47             }
     48 
     49         private:
     50             Json::Value root{ Json::ValueType::objectValue };
     51         };
     52     }
     53 
     54     void EnableAdminSetting(Execution::Context& context)
     55     {
     56         auto adminSettingString = context.Args.GetArg(Execution::Args::Type::AdminSettingEnable);
     57         BoolAdminSetting adminSetting = Settings::StringToBoolAdminSetting(adminSettingString);
     58         if (Settings::EnableAdminSetting(adminSetting))
     59         {
     60             context.Reporter.Info() << Resource::String::AdminSettingEnabled(AdminSettingToString(adminSetting)) << std::endl;
     61         }
     62         else
     63         {
     64             context.Reporter.Error() << Resource::String::EnableAdminSettingFailed(AdminSettingToString(adminSetting)) << std::endl;
     65         }
     66     }
     67 
     68     void DisableAdminSetting(Execution::Context& context)
     69     {
     70         auto adminSettingString = context.Args.GetArg(Execution::Args::Type::AdminSettingDisable);
     71         BoolAdminSetting adminSetting = Settings::StringToBoolAdminSetting(adminSettingString);
     72         if (Settings::DisableAdminSetting(adminSetting))
     73         {
     74             context.Reporter.Info() << Resource::String::AdminSettingDisabled(AdminSettingToString(adminSetting)) << std::endl;
     75         }
     76         else
     77         {
     78             context.Reporter.Error() << Resource::String::DisableAdminSettingFailed(AdminSettingToString(adminSetting)) << std::endl;
     79         }
     80     }
     81 
     82     void SetAdminSetting(Execution::Context& context)
     83     {
     84         auto adminSettingName = context.Args.GetArg(Execution::Args::Type::SettingName);
     85         auto adminSettingValue = context.Args.GetArg(Execution::Args::Type::SettingValue);
     86         StringAdminSetting adminSetting = Settings::StringToStringAdminSetting(adminSettingName);
     87         if (Settings::SetAdminSetting(adminSetting, adminSettingValue))
     88         {
     89             context.Reporter.Info() << Resource::String::SetAdminSettingSucceeded(LocIndString{ adminSettingName }, LocIndString{ adminSettingValue }) << std::endl;
     90         }
     91         else
     92         {
     93             context.Reporter.Error() << Resource::String::SetAdminSettingFailed(LocIndString{ adminSettingName }) << std::endl;
     94         }
     95     }
     96 
     97     void ResetAdminSetting(Execution::Context& context)
     98     {
     99         auto adminSettingName = context.Args.GetArg(Execution::Args::Type::SettingName);
    100 
    101         // Try as both bool and string setting as we don't know the type
    102         auto boolAdminSetting = Settings::StringToBoolAdminSetting(adminSettingName);
    103         auto stringAdminSetting = Settings::StringToStringAdminSetting(adminSettingName);
    104 
    105         if ((boolAdminSetting != Settings::BoolAdminSetting::Unknown && Settings::DisableAdminSetting(boolAdminSetting))
    106             || (stringAdminSetting != Settings::StringAdminSetting::Unknown && Settings::ResetAdminSetting(stringAdminSetting)))
    107         {
    108             context.Reporter.Info() << Resource::String::ResetAdminSettingSucceeded(LocIndString{ adminSettingName }) << std::endl;
    109         }
    110         else
    111         {
    112             context.Reporter.Error() << Resource::String::ResetAdminSettingFailed(LocIndString{ adminSettingName }) << std::endl;
    113         }
    114     }
    115 
    116     void ResetAllAdminSettings(Execution::Context& context)
    117     {
    118         Settings::ResetAllAdminSettings();
    119         context.Reporter.Info() << Resource::String::ResetAllAdminSettingsSucceeded << std::endl;
    120     }
    121 
    122     void OpenUserSetting(Execution::Context& context)
    123     {
    124         // Show warnings only when the setting command is executed.
    125         if (!User().GetWarnings().empty())
    126         {
    127             context.Reporter.Warn() << Resource::String::SettingLoadFailure << std::endl;
    128             for (const auto& warning : User().GetWarnings())
    129             {
    130                 auto warn = context.Reporter.Warn();
    131                 warn << warning.Message;
    132                 if (!warning.Path.empty())
    133                 {
    134                     if (warning.IsFieldWarning)
    135                     {
    136                         warn << ' ' << Resource::String::SettingsWarningField(warning.Path);
    137                     }
    138                     else
    139                     {
    140                         warn << ' ' << warning.Path;
    141                     }
    142                 }
    143 
    144                 if (!warning.Data.empty())
    145                 {
    146                     if (warning.IsFieldWarning)
    147                     {
    148                         warn << ' ' << Resource::String::SettingsWarningValue(warning.Data);
    149                     }
    150                     else
    151                     {
    152                         warn <<
    153                             std::endl <<
    154                             warning.Data;
    155                     }
    156                 }
    157 
    158                 warn << std::endl;
    159             }
    160         }
    161 
    162         User().PrepareToShellExecuteFile();
    163 
    164         auto filePathUTF16 = UserSettings::SettingsFilePath().wstring();
    165 
    166         // Some versions of windows will fail if no file extension association exists, other will pop up the dialog
    167         // to make the user pick their default.
    168         // Kudos to the terminal team for this workaround.
    169         HINSTANCE res = ShellExecuteW(nullptr, nullptr, filePathUTF16.c_str(), nullptr, nullptr, SW_SHOW);
    170         if (static_cast<int>(reinterpret_cast<uintptr_t>(res)) <= 32)
    171         {
    172             // User doesn't have file type association. Default to notepad
    173             AICLI_LOG(CLI, Info, << "Json file type association not found, using notepad.exe");
    174             ShellExecuteW(nullptr, nullptr, L"notepad", filePathUTF16.c_str(), nullptr, SW_SHOW);
    175         }
    176     }
    177 
    178     void ExportSettings(Execution::Context& context)
    179     {
    180         ExportSettingsJson exportSettingsJson;
    181 
    182         for (const auto& setting : GetAllBoolAdminSettings())
    183         {
    184             exportSettingsJson.AddAdminSetting(setting);
    185         }
    186 
    187         for (const auto& setting : GetAllStringAdminSettings())
    188         {
    189             exportSettingsJson.AddAdminSetting(setting);
    190         }
    191 
    192         context.Reporter.Info() << exportSettingsJson.ToJsonString() << std::endl;
    193     }
    194 }