-
Notifications
You must be signed in to change notification settings - Fork 129
Add side-by-side support to pwsh.exe #202
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
Conversation
|
I was under the assumption that the latest stable version would always be the default version. That is the only way to allow updates to continue to notify for new versions that are not installed. Otherwise if you had an older default, would Windows Update prompt you to upgrade to a newer stable version that you have installed? For version registration, I get why you suggest it is needed, but it adds some complexity. We could do registration like dotnet core does (I have no idea how they do it on xplat platforms but copying their example that is already in place should be easy). Or, we could instead do the following:
On the downside, if pwsh is installed in a system path, end users may not be able to install additional side-by-side versions in personal folders. But that's an upside as well, because it means that admins can control what is installed more easily. Thoughts? |
Can we add this explicitly? Although I doubt it will work for WindowsUpdate - as I remember it requires the same folder.
I guess Core uses directory structure: dir "C:\Program Files\dotnet\sdk\"
Directory: C:\Program Files\dotnet\sdk
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 17.04.2019 13:55 2.1.202
d----- 29.03.2019 19:08 2.1.504
d----- 17.04.2019 13:49 2.1.505
d----- 24.05.2019 16:07 2.1.507
d----- 24.05.2019 17:17 2.1.700
d----- 24.05.2019 17:38 2.2.300
d----- 20.05.2019 9:22 3.0.100-preview5-011568
d----- 24.05.2019 17:41 NuGetFallbackFolder
We could have well-known system and user folders Admins could control versions by policy (like GPO, we have RFC for implementing policies). |
Of course. I added two additional consideration sections for these. Those will need to be flushed out as I get additional feedback. |
Core isn't supported by Windows Update. Assuming that 7.0 is going to be LTS (I think that's impossible, since .NET 3.0.0 won't be LTS), should it not go in a folder that allows other versions of 7 to be installed around it? |
From https://dotnet.microsoft.com/platform/support/policy/dotnet-core:
So your point is that this won't happen until .NET Core 3.1? Yet from the PowerShell Team blog announcing PowerShell 7, they state:
That's a little confusing. That aside, yes, I think it should install automatically to a system/all users folder or a current user folder rather than be installable anywhere like PowerShell Core can today. |
One of the key motivators that I had behind this RFC was to reduce the drag. It is way too common for the community to push for downlevel solutions that are implemented in modules when we need core features in the language for current and future versions. In the past products took a hard dependency on a specific version of PowerShell (current documentation even states that the SCOM 2019 Management Console and Agent require PowerShell 2.0 or 3.0), and those dependencies slow down adoption of newer versions of PowerShell. @Jaykul pointed out in a side conversation that we have PowerShell Standard Libraries that can be used with by module authors to create modules that support many different versions of PowerShell (from Windows PowerShell 3.0 up to PowerShell Core 6.2.1, or from Windows PowerShell 5.1 up to PowerShell Core 6.2.1), and that resolves this problem. If PowerShell Standard indeed resolves this problem such that machines don't need to be unnecessarily locked to a specific LTS version of PowerShell, then there isn't really much need for SxS support in |
packages in the various package repositories (for `apt-get`, homebrew, and | ||
Chocolatey). The problem with this approach is that it does not support | ||
side-by-side installations at the command line. For example, if I have | ||
PowerShell Core 6.2.0 installed on macOS and I want to install PowerShell Core |
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 there a real need to have patch versions side-by-side? I would think the common scenario is 6.2, 7.0, 7.1.
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.
Indeed. And if PowerShell releases truly follow semver rules for versioning, I would expect 7.1 to be completely back compat with 7.0. So I'd only expect side-by-side support for major versions e.g. 5, 6, 7, 8, etc. Oh, looking ahead, you still need side-by-side support for previews as well but that is already handled today for major versions.
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.
We're explicitly not using semver for the version of PowerShell itself. Modules should use semver, but PS versions are just intended to signal relative size of feature sets, among other things.
|
||
```powershell | ||
|
||
# This returns a list of installed versions and their installation location as |
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.
I think it should be explicitly stated that this will only look in the expected installed locations and not search the entire filesystem. This means that custom deployments of the .zip/.tgz won't be found unless they are expanded in the same locations.
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.
Maybe use a file inventory that each version of PowerShell updates during install/uninstall. This method could read the file and list the versions there. Maybe with some validation that the source truly exists. Or detect Choco and list versions that way.
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.
if Windows is included here, the registry should be examined, IMO.
# This launches the latest version of PowerShell, gets the installation | ||
# location of the specified version, launches pwsh for that version, and exits | ||
# when the launched version exits | ||
pwsh -Version 6.2.1 |
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.
There are some implications we need to think about here. On Unix systems, we can leverage exec
so that there is a single pwsh process. On Windows, if you run this from cmd or PowerShell, the assumption is you want to use the current console window. So that means that pwsh
will start the newest one (as that's likely the one in PATH), which will then start a child process with the requested version. So you'll end up with two pwsh processes. There might be a way for pwsh.exe
to host the requested pwsh.dll
, but then you might have issues with pwsh.exe
being compiled against a different version of .NET Core. Need to think through this or just accept there's two processes.
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.
Within PowerShell at least, couldn't it intercept this request to start the native app called pwsh
with a specific -Version
param/arg, lookup that version and start it, passing it the rest of parameters except for -Version
? I'm not a fan of special-case code like this but it seems doable.
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.
It could be special cased in PowerShell itself, but not sure if it's worth it. Also, it seems that this is most useful for scripts using #Requires -Version X
to automatically run under those versions which isn't called out in this RFC.
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.
The “PowerShell.exe -Version x.x -File “C:\Path\To\script.ps1” could work here as well. It would be nice if a warning could be displayed, if that version isn’t installed and include what version was used instead.
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.
Also, I think it would be good to spawn a new child process, if calling a different “pwsh” from the console. This is expected behavior in Windows and *nix world when requesting a different shell. Unless a very good cleanup job was done of the current process, using some .dll swapping could get messy.
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.
I think there should be an error if the specified version isn't available, not using something else.
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 if the version is not installed? Will we fail or run upper version?
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.
It seems that if a specific version is requested and not found, it should not run and would return an error. If 6.2
is requested, then 6.2.2 would run, if available. It probably doesn't make sense to support any preview
releases with this feature.
make much sense to update older versions, so the most recently installed stable | ||
version should be treated as the default version to check for updates. | ||
|
||
Unfortunately I do not have much insight into what Windows Update requires. |
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.
Windows Update requires that the path to the binaries don't change. This means that we don't have even a complete version as the folder name hence it's just 6
and not 6.1
or 6.2
. This means that this may limit the usefulness to just major versions.
|
||
In order to keep systems and management processes running the way they must in | ||
an enterprise, many users have no choice but to stick with a downlevel version | ||
of Windows PowerShell for a very long time. There are even some organizations |
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.
s/some/many/
so that I can use automation built and tested against specific versions of PowerShell while still being able to use the latest version on the same system. | ||
|
||
## User Experience | ||
|
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.
Does this RFC include Windows? Or is it MacOS/Linux only? Where does WSL fit?
The examples are using a lot of third-party (by which I mean "non-Windows" and "non-PowerShell") commands. I find myself quite confused by this. I know what "apt get" is, but no clue what "brew" or "choco" or etc. do.
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.
brew
is apt
for macOS and choco
is apt
for Windows (3rd party so not available by default). This RFC needs to work with non-Windows.
`pwsh -version` support launching Windows PowerShell. That would allow users to | ||
launch any installed PowerShell version from `pwsh.exe`, making it easy to set | ||
up automation with one command to invoke. Arguments from `pwsh.exe` could be | ||
mapped to arguments on `powershell.exe`. |
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.
I think that Get-InstalledPSVersion
should definitely include Windows PowerShell, but I don't think the rest is really necessary given the binaries are different names. But it's not an important point.
containers can allow users to use different versions of PowerShell, I also | ||
suspect that most users don't know how to set that up, if they even use Docker | ||
at all. I think it would be easier for everyone if we could just launch the | ||
proper version of PowerShell via `pwsh.exe`. |
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.
Who is your audience?
I'm an admin scripter. And while I know what Docker/containers are, I certainly don't use them, nor do I know how (I have done a Windows container lab, but not using Docker). Lots of desktops/laptops don't have virtualization turned on, nor have a virtualizer installed nor will your average user know how to do so. But their admins may have very good reasons to need multiple versions of PS.
@PowerShell/powershell-committee had a long discussion on this one. While we understand the behavior you're proposing, we're not sure that the scenario is widespread. Windows PowerShell was updated much less frequently than PowerShell Core, and had more sweeping changes from version-to-version. Plus, Microsoft products were often tied to specific Windows PowerShell versions, and so side-by-side (SxS) became more necessary. To address this, we made SxS a high priority in PowerShell Core, allowing you to manage multiple installs. This was primarily enabled by .NET Core and the fact that we can ship app-local copies of the runtime with each version of PowerShell Core. For those that absolutely need SxS, we haven't heard that symlinks/xcopies don't meet their needs. There are a few other complexities here that also haven't been addressed:
Therefore, we're rejecting this one blocked on:
Our current recommendation until then is to use your own file path and symlinks. Ideally we should do something like |
This means that what we discussed before the 6 version release remains valid - we are doomed to have one main (system-wide) version. Updating versions of other products is the task of the manufacturers of these products.
Updating versions installed side-by-side is another task and we already have a RFC for detecting new versions at startup. So we could have some update channels - (1) Passive (Windows Update/WSUS) that is good for main, LTS versions and enterprises, (2) Active (at startup) that is good for side-by-side, personal versions (stable, preview, daily - that may be in PowerShell config file (ignored for main installation)). |
I'm moving to powershell in nix scripting specifically to get away from the mess that is If powershell itself wants to handle the version selection, I would expect each major version to be installable as an explicit version ( Then when writing scripts, one could explicitly target a required version ( I see both patterns in the wild. Sometimes you want to ensure your script runs exactly as expected with that explicit version, forcing the admins to configure the system for it, and putting the burden on them if they choose to break it with newer versions. Other times it's a library or generic tool that the author wants to support multiple versions, and allow the system to provide any minimum version, and thus the burden is on the script author to fix when it breaks with newer versions. Not sure if that's helpful / relevant, but imo the more "magic" we put in the way of version selection, the more risk of needing workarounds to workaround the magic when it doesn't work as we expect. |
No description provided.