@@ -302,6 +302,114 @@ namespace winrt::TerminalApp::implementation
302
302
settings.GlobalSettings ().FirstWindowPreference () == FirstWindowPreference::PersistedWindowLayout;
303
303
}
304
304
305
+ // Method Description:
306
+ // - This is a bit of trickiness: If we're running unelevated, and the user
307
+ // passed in only --elevate actions, the we don't _actually_ want to
308
+ // restore the layouts here. We're not _actually_ about to create the
309
+ // window. We're simply going to toss the commandlines
310
+ // Arguments:
311
+ // - <none>
312
+ // Return Value:
313
+ // - true if we're not elevated but all relevant pane-spawning actions are elevated
314
+ bool TerminalPage::ShouldImmediatelyHandoffToElevated (const CascadiaSettings& settings) const
315
+ {
316
+ if (!_startupActions || IsElevated ())
317
+ {
318
+ // there arent startup actions, or we're elevated. In that case, go for it.
319
+ return false ;
320
+ }
321
+
322
+ // Check that there's at least one action that's not just an elevated newTab action.
323
+ for (const auto & action : _startupActions)
324
+ {
325
+ NewTerminalArgs newTerminalArgs{ nullptr };
326
+
327
+ if (action.Action () == ShortcutAction::NewTab)
328
+ {
329
+ const auto & args{ action.Args ().try_as <NewTabArgs>() };
330
+ if (args)
331
+ {
332
+ newTerminalArgs = args.TerminalArgs ();
333
+ }
334
+ else
335
+ {
336
+ // This was a nt action that didn't have any args. The default
337
+ // profile may want to be elevated, so don't just early return.
338
+ }
339
+ }
340
+ else if (action.Action () == ShortcutAction::SplitPane)
341
+ {
342
+ const auto & args{ action.Args ().try_as <SplitPaneArgs>() };
343
+ if (args)
344
+ {
345
+ newTerminalArgs = args.TerminalArgs ();
346
+ }
347
+ else
348
+ {
349
+ // This was a nt action that didn't have any args. The default
350
+ // profile may want to be elevated, so don't just early return.
351
+ }
352
+ }
353
+ else
354
+ {
355
+ // This was not a new tab or split pane action.
356
+ // This doesn't affect the outcome
357
+ continue ;
358
+ }
359
+
360
+ // It's possible that newTerminalArgs is null here.
361
+ // GetProfileForArgs should be resilient to that.
362
+ const auto profile{ settings.GetProfileForArgs (newTerminalArgs) };
363
+ if (profile.Elevate ())
364
+ {
365
+ continue ;
366
+ }
367
+
368
+ // The profile didn't want to be elevated, and we aren't elevated.
369
+ // We're going to open at least one tab, so return false.
370
+ return false ;
371
+ }
372
+ return true ;
373
+ }
374
+
375
+ // Method Description:
376
+ // - Escape hatch for immediately dispatching requests to elevated windows
377
+ // when first launched. At this point in startup, the window doesn't exist
378
+ // yet, XAML hasn't been started, but we need to dispatch these actions.
379
+ // We can't just go through ProcessStartupActions, because that processes
380
+ // the actions async using the XAML dispatcher (which doesn't exist yet)
381
+ // - DON'T CALL THIS if you haven't already checked
382
+ // ShouldImmediatelyHandoffToElevated. If you're thinking about calling
383
+ // this outside of the one place it's used, that's probably the wrong
384
+ // solution.
385
+ // Arguments:
386
+ // - settings: the settings we should use for dispatching these actions. At
387
+ // this point in startup, we hadn't otherwise been initialized with these,
388
+ // so use them now.
389
+ // Return Value:
390
+ // - <none>
391
+ void TerminalPage::HandoffToElevated (const CascadiaSettings& settings)
392
+ {
393
+ if (!_startupActions)
394
+ {
395
+ return ;
396
+ }
397
+
398
+ // Hookup our event handlers to the ShortcutActionDispatch
399
+ _settings = settings;
400
+ _HookupKeyBindings (_settings.ActionMap ());
401
+ _RegisterActionCallbacks ();
402
+
403
+ for (const auto & action : _startupActions)
404
+ {
405
+ // only process new tabs and split panes. They're all going to the elevated window anyways.
406
+ if (action.Action () == ShortcutAction::NewTab || action.Action () == ShortcutAction::SplitPane)
407
+ {
408
+ _actionDispatch->DoAction (action);
409
+ }
410
+ }
411
+ }
412
+
305
413
// Method Description;
306
414
// - Checks if the current window is configured to load a particular layout
307
415
// Arguments:
@@ -1638,7 +1746,30 @@ namespace winrt::TerminalApp::implementation
1638
1746
std::shared_ptr<Pane> newPane)
1639
1747
{
1640
1748
const auto focusedTab{ _GetFocusedTabImpl () };
1641
- _SplitPane (*focusedTab, splitDirection, splitSize, newPane);
1749
+
1750
+ // Clever hack for a crash in startup, with multiple sub-commands. Say
1751
+ // you have the following commandline:
1752
+ //
1753
+ // wtd nt -p "elevated cmd" ; sp -p "elevated cmd" ; sp -p "Command Prompt"
1754
+ //
1755
+ // Where "elevated cmd" is an elevated profile.
1756
+ //
1757
+ // In that scenario, we won't dump off the commandline immediately to an
1758
+ // elevated window, because it's got the final unelevated split in it.
1759
+ // However, when we get to that command, there won't be a tab yet. So
1760
+ // we'd crash right about here.
1761
+ //
1762
+ // Instead, let's just promote this first split to be a tab instead.
1763
+ // Crash avoided, and we don't need to worry about inserting a new-tab
1764
+ // command in at the start.
1765
+ if (!focusedTab && _tabs.Size () == 0 )
1766
+ {
1767
+ _CreateNewTabFromPane (newPane);
1768
+ }
1769
+ else
1770
+ {
1771
+ _SplitPane (*focusedTab, splitDirection, splitSize, newPane);
1772
+ }
1642
1773
}
1643
1774
1644
1775
// Method Description:
0 commit comments