terminal icon indicating copy to clipboard operation
terminal copied to clipboard

Introduce PowerShell installer stub

Open carlos-zamora opened this issue 9 months ago • 17 comments

Summary of the Pull Request

Adds an "Install Latest PowerShell" stub to the new tab menu that installs the latest PowerShell on your machine when invoked. This is generated via a new PowershellInstallationProfileGenerator and leverages the new Extensions page to allow enabling/disabling the extension. The leftover stub is also automatically deleted to create a much cleaner experience.

References and Relevant Issues

Internal Spec: https://microsoft-my.sharepoint-df.com/:w:/p/chrnguyen/EchlDFoWsTBIudqQzVckHGABJ7zErJPK8aiLrS9nnFrlyw?e=QdmB1w Targets #18633

Validation steps performed

  • PowerShell Installed
    • ✅ no stub in new tab menu
    • ✅ SUI > Extensions: no added profile
  • PowerShell not installed
    • ✅ installer stub is in new tab menu
    • ✅ SUI > Extensions: "added profile" populated
  • PowerShell not installed --> installed
    • ✅ installer stub not in new tab menu
    • ✅ SUI > Extensions: "added profile" not populated

carlos-zamora avatar Feb 28 '25 02:02 carlos-zamora

Demo

Note 1: It's a really long gif, but it's worth it! Note 2: This is running on a VM in Windows 10 because I didn't want to uninstall/reinstall PowerShell on my main machine over-and-over again.

powershell stub

carlos-zamora avatar Feb 28 '25 02:02 carlos-zamora

@nguyen-dows @StevenBucher98 @DHowett Take a look at the demo above. Let me know what you think and if anything's missing 😊

I worked hard to make that stub go away afterwards because I got annoyed by it, so I figured everybody else would too. Also added a comment into the JSON stubs. Not sure how many people are gonna read it, but it's something (and better than the profile disappearing from the settings UI, but the empty extension still being there).

Also made the decision to make the installer interactive because if you're installing it, I'm guessing you may want to configure it and be well aware that you're installing something.

One annoying thing is that the dynamic profile generators only trigger if you close and open terminal again. I tried to help make that more clear by adding a little localized phrase in the stub session. Not perfect, but it's something.

One concern I have is this: is it possible for somebody to modify the stub to install malicious.exe instead? I'm pretty sure the answer to this is "no" because we're hashing the settings file, so we're already covered, but wanted to bring it to your attention.

carlos-zamora avatar Feb 28 '25 02:02 carlos-zamora

I think there was some discussion before about disabling this for enterprises. I know the files for that are:

  • https://github.com/microsoft/terminal/blob/main/policies/WindowsTerminal.admx
  • https://github.com/microsoft/terminal/blob/main/policies/en-US/WindowsTerminal.adml

Is there a way to add Windows.Terminal.InstallPowerShell by default? Is that something we want to do?

carlos-zamora avatar Feb 28 '25 02:02 carlos-zamora

I didn't look to see where the PowerShell installer was coming from. You could in theory use WinGet to install PowerShell interactively for this which would give you the hash of the PowerShell installer as a sanity check. I think the main concern is whether the default "winget" source is available to the user. In some enterprise environments, it might be removed or blocked. I'm not trying to throw wrenches in the works here, but just wanted to collaborate if it would improve the experience for the user.

denelon avatar Mar 01 '25 20:03 denelon

Lol, and now the page refreshes and I see @mdanish-kh suggesting the "winget" source as well as interactive... :)

denelon avatar Mar 01 '25 20:03 denelon

You might want to check if the winget source is configured before just trying to use it.

denelon avatar Mar 01 '25 20:03 denelon

You might want to check if the winget source is configured before just trying to use it.

Would the simplest way be checking against the output of winget source export | ConvertFrom-Json? Because if the winget source has been blocked by the Group Policy Enable App Installer Default Source, it will not show up in the output of winget source export

mdanish-kh avatar Mar 01 '25 21:03 mdanish-kh

That might be a good way to make the determination. GPO or a user who removed the source would both give an indication via source export (by the lack of having the "winget" source).

denelon avatar Mar 03 '25 15:03 denelon

I am staunchly opposed to Terminal running a command to determine whether it should generate a profile. @denelon and @mdanish-kh, is there a way to figure this out without spawning and waiting for winget.exe?

FWIW, the WSL team once told us they didn't have an API to list Linux distributions and they recommended shelling out to wsl -l. Even in the best case, that added hundreds of ms to our startup time. In the worst, it added ten seconds because sometimes their COM server was down.

Winget is a packaged application. Given how unreliable packaged apps are, I am not introducing the launch of another packaged application to our startup process.

DHowett avatar Mar 03 '25 15:03 DHowett

I don't know the internal mechanics of the profile generation in Terminal. I was just looking at the mechanics involved to have WinGet install PowerShell, and ensuring we weren't passing any implicit agreements for the user without their knowledge or consent, and making sure the package is available before attempting to install it.

Most of the WinGet core functionality is in COM, but there are certainly cold-start cases that can be slow, and shelling out to WinGet or the PowerShell cmdlets can take more time than one might want for a start-up scenario.

"is there a way to figure this out"

I'm not sure what you are referring to for this comment.

denelon avatar Mar 03 '25 15:03 denelon

Overall the experience looks great to me!

StevenBucher98 avatar Mar 03 '25 17:03 StevenBucher98

"is there a way to figure this out"

I'm not sure what you are referring to for this comment.

Sorry, what I mean is... we don't want to display the PowerShell Installer if the user's not going to be able to use it either due to enterprise management (winget is disabled, source is disabled, our dynamic profile generators are disabled), user management (winget is disabled, source is uninstalled, our dynamic profile generators are disabled), or any other thing that may prevent the user from being successful here.

We need to be able to make that determination quickly with the information available in native data stores available in-proc, because there's a chance we will be doing it on every launch of Terminal.

DHowett avatar Mar 03 '25 18:03 DHowett

OK, I understand the scenario a bit better now. I'm not sure if we have anything that would be "faster", but maybe @JohnMcPMS has some ideas.

denelon avatar Mar 03 '25 18:03 denelon

I assume that the goal is to avoid showing this option in the face of guaranteed failure. I also assume there is at least some aversion to installing the MSIX version from the Store (I don't know its current support status).

If those are both true, then I think you must run/attempt to run a winget process to get the answer. Any attempt to short circuit that by reading GP registry would not be a supported path.

JohnMcPMS avatar Mar 03 '25 21:03 JohnMcPMS

Note to self: tested the new version by manually changing isPowerShellInstalled to false. It should work as expected, but I want to verify it again with a fresh machine. Unfortunately, I need to set up a VM again to test that out, so that'll be something for me to do tomorrow. I'll report back.

carlos-zamora avatar Apr 17 '25 00:04 carlos-zamora

@check-spelling-bot Report

:red_circle: Please review

See the :open_file_folder: files view, the :scroll:action log, or :memo: job summary for details.

Unrecognized words (1)

Schmes

These words are not needed and should be removed abcd ABCDEFGHIJ abcdefghijk ABCDEFGHIJKLMNOPQRS ABCDEFGHIJKLMNOPQRST ABCDEFGHIJKLMNOPQRSTUVWXY allocs appium Argb asan autocrlf backported bytebuffer cac CLE codenav codepath commandline COMMITID componentization constness dealloc deserializers DISPATCHNOTIFY DTest entrypoints EVENTID FINDUP fuzzer hlocal hstring IInput Interner keyscan Munged numlock offboarded pids positionals Productize pseudoterminal remoting renamer roadmap ruleset SELECTALL somefile Stringable tearoff TODOs touchpad TREX Unregistering USERDATA vectorize viewports wsl

To accept these unrecognized words as correct and remove the previously acknowledged and now absent words, you could run the following commands

... in a clone of the [email protected]:microsoft/terminal.git repository on the dev/cazamor/sui/ext-page/powershell-stub branch (:information_source: how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/v0.0.24/apply.pl' |
perl - 'https://github.com/microsoft/terminal/actions/runs/14849554154/attempts/1'

Errors (1)

See the :open_file_folder: files view, the :scroll:action log, or :memo: job summary for details.

:x: Errors Count
:x: ignored-expect-variant 2

See :x: Event descriptions for more information.

:pencil2: Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/allow/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/allow/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

:microscope: You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. :wink:

If the flagged items are :exploding_head: false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it, try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

github-actions[bot] avatar May 06 '25 01:05 github-actions[bot]

Feedback from 6/10 bug bash

  • [ ] I am not going to restart Terminal for you. Terminal knows I launched it, knows the process ran and completed, and knows that my intent was to install the new powershell. Can we just reload when this profile finishes?
  • [ ] When we do, if the default profile is set to WindowsPS, can we ask users if they want to make it NewPS?

carlos-zamora avatar Jun 12 '25 17:06 carlos-zamora