-
Notifications
You must be signed in to change notification settings - Fork 8.6k
Introduce PowerShell installer stub #18639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev/cazamor/sui/extensions-page
Are you sure you want to change the base?
Introduce PowerShell installer stub #18639
Conversation
@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 think there was some discussion before about disabling this for enterprises. I know the files for that are:
Is there a way to add |
7a426b4
to
9842bdc
Compare
src/cascadia/TerminalSettingsModel/PowershellInstallationProfileGenerator.cpp
Outdated
Show resolved
Hide resolved
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. |
Lol, and now the page refreshes and I see @mdanish-kh suggesting the "winget" source as well as interactive... :) |
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 |
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). |
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 FWIW, the WSL team once told us they didn't have an API to list Linux distributions and they recommended shelling out to 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. |
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.
I'm not sure what you are referring to for this comment. |
Overall the experience looks great to me! |
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. |
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. |
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. |
WslDistroGenerator wslGenerator{}; | ||
_executeGenerator(wslGenerator); | ||
|
||
AzureCloudShellGenerator acsGenerator{}; | ||
_executeGenerator(acsGenerator); | ||
|
||
VisualStudioGenerator vsGenerator{}; | ||
_executeGenerator(vsGenerator); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really necessary to extend the lifetime of these generators? They only get destroyed at the end of the scope now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What motivated this change was that the PowershellCoreProfileGenerator
already does all the work of finding the existing PowerShell instances; it uses that information to generate (and configure) the appropriate amount of PowerShell profiles.
We need an instance of the profile generator lying around so that we can reuse that information. That way, if we detect that there's an instance of PowerShell installed, we hide the installer stub.
Admittedly, it's not ideal, but its all in one function. Any ideas on how to get around it? Is it worth making the PowershellCoreProfileGenerator special? Or maybe I should pull out the GetPowerShellInstances()
code into a static function and undo the work of keeping the generators around (I'll give that a try).
src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp
Outdated
Show resolved
Hide resolved
src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp
Outdated
Show resolved
Hide resolved
|
||
// We want the comment to be the first thing in the object, | ||
// "closeOnExit" is the first property, so target that. | ||
auto fragExtJson = _parseJSON(til::u16u8(fragExt->Json())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest, I kind of forgot how the extension code works, but this still seems kind of hacky to me.
The fragment in this case is based on an extension, right? Don't extensions generate profiles only? I'm missing the big picture how we go from profiles to JSON here, hence my confusion. Basically, since extensions generate profiles (including PowershellInstallationProfileGenerator
), my assumption would be that this function doesn't need to deal with parsing JSON at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh this section is SUPER hacky! The sole purpose of this is to add the JSON comment so it appears like this:
So yeah, we have to parse the JSON, add the comment, then store the new JSON with the comment back in.
We have to do it twice:
- the settings.json blob representing the entire fragment extension
- the generated profile itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Figured it'd be good to try and tell the user that this profile only appears if PowerShell is not installed. It's a weird little behavior that I figured at least a JSON comment would help point out, even if not many people read the JSON comment.
9842bdc
to
71be4ee
Compare
Note to self: tested the new version by manually changing |
if (!isPowerShellInstalled) | ||
{ | ||
// Only generate the installer stub profile if PowerShell isn't installed. | ||
PowershellInstallationProfileGenerator pwshInstallationGenerator{}; | ||
_executeGenerator(pwshInstallationGenerator); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using this as a thread to track some of the top-level discussion around preemptively disabling the installer generator. Specifically Dustin's concern here:
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.
Motivation (link): (paraphrasing) out-of-proc query can REALLY impact our startup time
Solution discussion from John (link):
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.
Sounds like we may need to think of some other way to preemptively disable the installer generator. I'll noodle on this more tomorrow, but again, using this thread as a nicer way of tracking it.
const auto isPowerShellInstalled = !powerShellGenerator.GetPowerShellInstances().empty(); | ||
if (!isPowerShellInstalled) | ||
{ | ||
// Only generate the installer stub profile if PowerShell isn't installed. | ||
PowershellInstallationProfileGenerator pwshInstallationGenerator{}; | ||
_executeGenerator(pwshInstallationGenerator); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 Huh, a side effect of putting this in a scope and conditionally executing the installer's generator is that now the generator only appears in the Extensions page if PowerShell is not installed. This is because all the work to register the generator for the settings UI is in _executeGenerator()
.
I'm honestly kinda ok with this change. It means that for anybody that has PowerShell installed already, they won't even see the installer generator anywhere. But if the user doesn't have PowerShell 7 installed, they get the installer stub. From that point, the user can also manually disable the generator via the Extensions page.
f650f45
to
b963d60
Compare
a00f333
to
4b35462
Compare
b963d60
to
f25e6fe
Compare
4b35462
to
36d28e2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
…xt-page/powershell-stub
…xt-page/powershell-stub
@check-spelling-bot Report🔴 Please reviewSee the 📂 files view, the 📜action log, or 📝 job summary for details.Unrecognized words (1)Schmes These words are not needed and should be removedabcd 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 wslTo 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 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 📂 files view, the 📜action log, or 📝 job summary for details.
See ❌ Event descriptions for more information. ✏️ Contributor please read thisBy 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:
See the 🔬 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. 😉 If the flagged items are 🤯 false positivesIf items relate to a ...
|
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