19
19
#if TIL_FEATURE_DYNAMICSSHPROFILES_ENABLED
20
20
#include " SshHostGenerator.h"
21
21
#endif
22
+ #include " PowershellInstallationProfileGenerator.h"
22
23
23
24
#include " ApplicationState.h"
24
25
#include " DefaultTerminal.h"
@@ -209,26 +210,58 @@ Json::StreamWriterBuilder SettingsLoader::_getJsonStyledWriter()
209
210
// (meaning profiles specified by the application rather by the user).
210
211
void SettingsLoader::GenerateProfiles ()
211
212
{
212
- auto generateProfiles = [&](const IDynamicProfileGenerator& generator) {
213
+ auto generateProfiles = [&](IDynamicProfileGenerator& generator) {
213
214
if (!_ignoredNamespaces.contains (generator.GetNamespace ()))
214
215
{
215
216
_executeGenerator (generator, inboxSettings.profiles );
216
217
}
217
218
};
218
219
219
- generateProfiles (PowershellCoreProfileGenerator{});
220
- generateProfiles (WslDistroGenerator{});
221
- generateProfiles (AzureCloudShellGenerator{});
222
- generateProfiles (VisualStudioGenerator{});
220
+ {
221
+ PowershellCoreProfileGenerator powerShellGenerator{};
222
+ generateProfiles (powerShellGenerator);
223
+
224
+ if (Feature_PowerShellInstallerProfileGenerator::IsEnabled ())
225
+ {
226
+ if (!powerShellGenerator.GetPowerShellInstances ().empty ())
227
+ {
228
+ // If PowerShell is installed, mark the installer profile for deletion
229
+ const winrt::guid profileGuid{ L" {965a10f2-b0f2-55dc-a3c2-2ddbf639bf89}" };
230
+ for (const auto & profile : userSettings.profiles )
231
+ {
232
+ if (profile->Guid () == profileGuid)
233
+ {
234
+ profile->Deleted (true );
235
+ break ;
236
+ }
237
+ }
238
+ }
239
+ else
240
+ {
241
+ // Only generate the installer stub profile if PowerShell isn't installed.
242
+ PowershellInstallationProfileGenerator pwshInstallationGenerator{};
243
+ generateProfiles (pwshInstallationGenerator);
244
+ }
245
+ }
246
+ }
247
+ WslDistroGenerator wslGenerator{};
248
+ generateProfiles (wslGenerator);
249
+
250
+ AzureCloudShellGenerator acsGenerator{};
251
+ generateProfiles (acsGenerator);
252
+
253
+ VisualStudioGenerator vsGenerator{};
254
+ generateProfiles (vsGenerator);
223
255
#if TIL_FEATURE_DYNAMICSSHPROFILES_ENABLED
224
- generateProfiles (SshHostGenerator{});
256
+ SshHostGenerator sshGenerator{};
257
+ generateProfiles (sshGenerator);
225
258
#endif
226
259
}
227
260
228
261
// Generate ExtensionPackage objects from the profile generators.
229
262
void SettingsLoader::GenerateExtensionPackagesFromProfileGenerators ()
230
263
{
231
- auto generateExtensionPackages = [&](const IDynamicProfileGenerator& generator) {
264
+ auto generateExtensionPackages = [&](IDynamicProfileGenerator& generator) {
232
265
std::vector<winrt::com_ptr<implementation::Profile>> profilesList;
233
266
_executeGenerator (generator, profilesList);
234
267
@@ -255,17 +288,60 @@ void SettingsLoader::GenerateExtensionPackagesFromProfileGenerators()
255
288
extPkg->Icon (hstring{ generator.GetIcon () });
256
289
};
257
290
258
- // TODO CARLOS: is there a way to deduplicate this list?
259
- // Is it even worth it if we're adding special logic for the PwshInstallerGenerator PR?
260
- generateExtensionPackages (PowershellCoreProfileGenerator{});
261
- generateExtensionPackages (WslDistroGenerator{});
262
- generateExtensionPackages (AzureCloudShellGenerator{});
263
- generateExtensionPackages (VisualStudioGenerator{});
291
+ PowershellCoreProfileGenerator powerShellGenerator{};
292
+ generateExtensionPackages (powerShellGenerator);
293
+
294
+ if (Feature_PowerShellInstallerProfileGenerator::IsEnabled ())
295
+ {
296
+ PowershellInstallationProfileGenerator pwshInstallationGenerator{};
297
+ generateExtensionPackages (pwshInstallationGenerator);
298
+ _patchInstallPowerShellProfile ();
299
+ }
300
+
301
+ WslDistroGenerator wslGenerator{};
302
+ generateExtensionPackages (wslGenerator);
303
+
304
+ AzureCloudShellGenerator acsGenerator{};
305
+ generateExtensionPackages (acsGenerator);
306
+
307
+ VisualStudioGenerator vsGenerator{};
308
+ generateExtensionPackages (vsGenerator);
264
309
#if TIL_FEATURE_DYNAMICSSHPROFILES_ENABLED
265
- generateExtensionPackages (SshHostGenerator{});
310
+ SshHostGenerator sshGenerator{};
311
+ generateExtensionPackages (sshGenerator);
266
312
#endif
267
313
}
268
314
315
+ // Retrieve the "Install Latest PowerShell" profile and add a comment to the JSON to indicate it's conditionally applied
316
+ void SettingsLoader::_patchInstallPowerShellProfile ()
317
+ {
318
+ const hstring pwshInstallerNamespace{ PowershellInstallationProfileGenerator::Namespace };
319
+ if (extensionPackageMap.contains (pwshInstallerNamespace))
320
+ {
321
+ if (const auto & fragExtList = extensionPackageMap[pwshInstallerNamespace]->Fragments (); fragExtList.Size () > 0 )
322
+ {
323
+ auto fragExt = get_self<FragmentSettings>(fragExtList.GetAt (0 ));
324
+
325
+ // We want the comment to be the first thing in the object,
326
+ // "closeOnExit" is the first property, so target that.
327
+ auto fragExtJson = _parseJSON (til::u16u8 (fragExt->Json ()));
328
+ fragExtJson[JsonKey (ProfilesKey)][0 ][" closeOnExit" ].setComment (til::u16u8 (fmt::format (FMT_COMPILE (L" // {}" ), RS_ (L" PowerShellInstallationProfileJsonComment" ))), Json::CommentPlacement::commentBefore);
329
+ fragExt->Json (hstring{ til::u8u16 (Json::writeString (_getJsonStyledWriter (), fragExtJson)) });
330
+
331
+ if (const auto & profileEntryList = fragExt->NewProfilesView (); profileEntryList.Size () > 0 )
332
+ {
333
+ auto profileEntry = get_self<FragmentProfileEntry>(profileEntryList.GetAt (0 ));
334
+
335
+ // We want the comment to be the first thing in the object,
336
+ // "closeOnExit" is the first property, so target that.
337
+ auto profileJson = _parseJSON (til::u16u8 (profileEntry->Json ()));
338
+ profileJson[" closeOnExit" ].setComment (til::u16u8 (fmt::format (FMT_COMPILE (L" // {}" ), RS_ (L" PowerShellInstallationProfileJsonComment" ))), Json::CommentPlacement::commentBefore);
339
+ profileEntry->Json (hstring{ til::u8u16 (Json::writeString (_getJsonStyledWriter (), profileJson)) });
340
+ }
341
+ }
342
+ }
343
+ }
344
+
269
345
// A new settings.json gets a special treatment:
270
346
// 1. The default profile is a PowerShell 7+ one, if one was generated,
271
347
// and falls back to the standard PowerShell 5 profile otherwise.
@@ -1084,7 +1160,7 @@ bool SettingsLoader::_addOrMergeUserColorScheme(const winrt::com_ptr<implementat
1084
1160
1085
1161
// As the name implies it executes a generator.
1086
1162
// Generated profiles are added to .inboxSettings. Used by GenerateProfiles().
1087
- void SettingsLoader::_executeGenerator (const IDynamicProfileGenerator& generator, std::vector<winrt::com_ptr<implementation::Profile>>& profilesList)
1163
+ void SettingsLoader::_executeGenerator (IDynamicProfileGenerator& generator, std::vector<winrt::com_ptr<implementation::Profile>>& profilesList)
1088
1164
{
1089
1165
const auto generatorNamespace = generator.GetNamespace ();
1090
1166
const auto previousSize = profilesList.size ();
@@ -1648,7 +1724,11 @@ void CascadiaSettings::_resolveNewTabMenuProfiles() const
1648
1724
auto activeProfileCount = gsl::narrow_cast<int >(_activeProfiles.Size ());
1649
1725
for (auto profileIndex = 0 ; profileIndex < activeProfileCount; profileIndex++)
1650
1726
{
1651
- remainingProfilesMap.emplace (profileIndex, _activeProfiles.GetAt (profileIndex));
1727
+ const auto & profile = _activeProfiles.GetAt (profileIndex);
1728
+ if (!profile.Deleted ())
1729
+ {
1730
+ remainingProfilesMap.emplace (profileIndex, _activeProfiles.GetAt (profileIndex));
1731
+ }
1652
1732
}
1653
1733
1654
1734
// We keep track of the "remaining profiles" - those that have not yet been resolved
0 commit comments