Skip to content
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

Obscure launching method #2348

Closed
mintty opened this issue Jul 17, 2017 · 60 comments
Closed

Obscure launching method #2348

mintty opened this issue Jul 17, 2017 · 60 comments

Comments

@mintty
Copy link

mintty commented Jul 17, 2017

Users need to know how WSL is actually invoked, but this is artificially obscured (no target info for Start Menu icons, weird installation redirection).
There needs to be transparent information about the WSL installation that exist on the system (or for the user), and how to invoke each of them, and which icon to use for it.

@fjsuarez
Copy link

The target for the icon on my Start Menu shows C:\Windows\System32\bash.exe ~
I'm not sure if that is what you are talking about.

@benhillis
Copy link
Member

@mintty - I believe he's talking about the tiles that get installed when you install a WSL distro from the store.

@ghost
Copy link

ghost commented Jul 18, 2017

Actually I did not even know where bash.exe was situated - now I know thanks to fjsuarez. :)

I think that mintty has one additional point; when not only ubuntu is available but, say, opensuse, and perhaps even more, then people may be a bit confused as to what is installed where. E .g. what is linked at /mnt/c - and what about other distributions, what do they install and so forth. Good documentation would be very helpful here but I am sure that once features/functionality work as designed, documentation will also be provided.

@mintty
Copy link
Author

mintty commented Jul 18, 2017

C:\Windows\System32\bash.exe is the launcher for the preliminary version.
With the current update, they changed installation. WSL is now available from the Windows Store, and even without another of the planned distros installed, it is very obscure where to find it:
For the current version, the launcher is %PROGRAMFILES%/WindowsApps/CanonicalGroupLimited.Ubu ntuonWindows_1604.2017.711.0_x64__79rhkp1fndgsc/ubuntu.exe and the icon is %PROGRAMFILES%/WindowsApps/CanonicalGroupLimited.UbuntuonWindows_1604.2017.711.0_x64__79rhkp1fndgsc/images/icon.ico.
This cryptic name does not look version-compatible, and what will it be for other distros?

@mintty
Copy link
Author

mintty commented Jul 18, 2017

Actually, the installed distros are listed per user in the registry under [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss], with their distro folders (BasePath). However, the names of the launcher and icon are not registered there.

@factormystic
Copy link

factormystic commented Jul 18, 2017

Can't you just use c:\windows\system32\wsl.exe?

@leojbgiusti
Copy link

I read somewhere, probably a comment on the blog post announcing the new store versions that bash.exe will continue to work launching any of the store distros. Also the long cryptic paths are a result of the store.

@mintty
Copy link
Author

mintty commented Jul 18, 2017

Maybe. But if there are (in future) multiple distros installed, how would I tell bash.exe which to use?
And how do I identify the respective icon for each one?

@leojbgiusti
Copy link

Use the new wslconfig command. Scott Hanselman has a blog post about it all. https://www.hanselman.com/blog/UbuntuNowInTheWindowsStoreUpdatesToLinuxOnWindows10AndImportantTips.aspx

@fpqc
Copy link

fpqc commented Jul 18, 2017

@mintty Here:

C:\Windows\System32>where ubuntu
C:\Users\fpqc\AppData\Local\Microsoft\WindowsApps\ubuntu.exe

C:\Windows\System32>echo %PATH%
C:\Program Files\ImageMagick-7.0.5-Q16;C:\Program Files (x86)\Python35-32\Scripts\;C:\Program Files (x86)\Python35-32\;C:\ProgramData\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Users\fpqc\AppData\Local\Microsoft\WindowsApps;....

It appears to be a symlink or junction to the actual executable. It's not showing up as a link for some reason, but that's how the magic happens. The actual kind of link they're using here is a complete mystery to me haha. It has size 0 but isn't showing up as junction or symlink.

@mintty
Copy link
Author

mintty commented Jul 18, 2017

@leojbgiusti / wslconfig:
Ah, that looks like giving almost the missing information, thanks. I'll try later.
Still missing though, how to find respective icons.

@mintty
Copy link
Author

mintty commented Jul 18, 2017

@fpqc: where ubuntu does not help about multiple distros...

@fpqc
Copy link

fpqc commented Jul 18, 2017

@benhillis Do you have any idea what kind of mysterious symlink (or something else) that is in the %localappdata%\Microsoft\WindowsApps directory? I tried poking it and prodding it and opening it up in a hex editor and I got nothing out of it. I guess it's maybe a special kind of reparse point?

@benhillis
Copy link
Member

@fpqc - it's an execution alias: https://docs.microsoft.com/en-us/windows/uwp/porting/desktop-to-uwp-extensions

@fpqc
Copy link

fpqc commented Jul 18, 2017

Ah thanks! Is the file itself just an empty ordinary file?

@benhillis
Copy link
Member

@fpqc - they are implemented as custom reparse points. https://msdn.microsoft.com/en-us/library/windows/desktop/aa365503(v=vs.85).aspx

@fpqc
Copy link

fpqc commented Jul 18, 2017

Super cool! Are there any plans to extend dir and mklink to be able to use them, because right now they display no information with the usual tools.

@benhillis
Copy link
Member

@fpqc - I'm not sure about future plans, since that's not an area my team owns.

@fpqc
Copy link

fpqc commented Jul 18, 2017

@mintty Yes it does. That directory localappdata%\Microsoft\WindowsApps is the location of the execution alias that gets picked up in the user's PATH. All of the distros installed should be in that directory with their own execution aliases.

@fpqc
Copy link

fpqc commented Jul 18, 2017

@benhillis Alright maybe I'll ask Rich on Twitter and he'll ping in the right person.

@benhillis
Copy link
Member

@fpqc - Yeah Rich (@bitcrazed) would definitely know the right people to get in touch with about execution aliases. The design is pretty new and I'm not sure if it's fully realized yet.

@fpqc
Copy link

fpqc commented Jul 18, 2017

Yeah, it's newer than I expected, like brand new 16226.

Here's their blogpost https://blogs.windows.com/buildingapps/2017/07/05/command-line-activation-universal-windows-apps/

@zadjii-msft
Copy link
Member

zadjii-msft commented Jul 18, 2017

I'll just hop on before Rich comes down to my office and pings me manually.

Yes, %localappdata%\Microsoft\WindowsApps is where the execution aliases live. Careful though - distros aren't the only ones to use those, so you have to have a way to find only the distros. Note that there is another copy of the execution alias under the directory corresponding to the app in that folder - eg %localappdata%\Microsoft\WindowsApps\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc

Yes, the distros are registered under the Lxss key. Beware that changing any of these values could corrupt that app's install, but you may want to look at the PackageFamilyName key.

@mintty
Copy link
Author

mintty commented Jul 18, 2017

@zadjii-msft

... figure out how to enumerate all of the execution aliases that correspond to distros :)

Thanks, with wslconfig or the Lxss key there are two fairly easy ways. But I'd appreciate if you can tell us how to find the proper icon for each respective distro.

@fpqc
Copy link

fpqc commented Jul 18, 2017

@zadjii-msft No worries, I think @mintty is trying to have the wsltty installer pick up the distros and launchy mintty and wslbridge for each distro (which is why he cares about the icons).

@zadjii-msft
Copy link
Member

@mintty I'm afraid I don't know how to find the icons. There was a console PR a while back that mentioned "Make the console host try using the window title as a search path for the icon." but I don't know how that works exactly, or if it's relevant in this case.

I'd look at C:\Program Files\WindowsApps, but you'd need admin privileges to poke around in there so I'm not sure it'd be that useful.

Sorry I can't be more help.

@therealkenc
Copy link
Collaborator

but I don't know how that works exactly, or if it's relevant in this case.

https://stackoverflow.com/questions/37417757/extract-icon-from-uwp-application

@mintty
Copy link
Author

mintty commented Jul 18, 2017

Thanks, that sounds like a theoretical solution; however, I don't feel like writing an application and spending hours or days on reverse engineering its problems for such a simple requirement. There should be an MS command-line tool (or maybe 3rd party tool) to simply extract the icon from the exe.

@therealkenc
Copy link
Collaborator

therealkenc commented Jul 23, 2017

There should be an MS command-line tool (or maybe 3rd party tool)

EnumWSL (source).

LxUID: {12345678-1234-5678-0123-456789abcdef}
DistributionName: Legacy
LaunchPath: "C:\WINDOWS\system32\bash.exe"
IconPath: "C:\Users\ken\AppData\Local\lxss\bash.ico"
IsDefault: true

LxUID: {b405c97d-5ee3-4d1f-a23c-13d4b4a4c88d}
DistributionName: openSUSE-42
PackageFamilyName: 46932SUSE.openSUSELeap42.2_022rs5jcyhyac
LaunchPath: "C:\Users\ken\AppData\Local\Microsoft\WindowsApps\openSUSE-42.exe"
IconPath: "C:\Program Files\WindowsApps\46932SUSE.openSUSELeap42.2_1.0.3.0_x64__022rs5jcyhyac\images\icon.ico"
IsDefault: false

LxUID: {e23840cc-dc7b-451f-9b14-28300d1474b7}
DistributionName: Ubuntu
PackageFamilyName: CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc
LaunchPath: "C:\Users\ken\AppData\Local\Microsoft\WindowsApps\Ubuntu.exe"
IconPath: "C:\Program Files\WindowsApps\CanonicalGroupLimited.UbuntuonWindows_1604.2017.711.0_x64__79rhkp1fndgsc\images\icon.ico"
IsDefault: false

@benhillis
Copy link
Member

@therealkenc - Even if the applications are moved folders in the app install directory are replaced by reparse points, so in theory the "old" paths will still work.

@mintty
Copy link
Author

mintty commented Jul 25, 2017

@benhillis, is there an option, like in the Legacy distro, to start the WSL shell in a specific directory rather than the WSL home directory?

@benhillis
Copy link
Member

@mintty - That would be up to each individual distribution. They are in control of their launcher executable and what arguments it supports.

Once you have a distribution installed you can still use bash.exe / wsl.exe to launch it which support the ~ operator. You simply have to set it to your user's default using the wslconfig.exe command line too. Afterwards when you launch bash.exe or wsl.exe it will use whichever distro you specified.

@zadjii-msft
Copy link
Member

@mintty by default you should be able to, yes. For example, ubuntu run bash will launch ubuntu's bash in the current directory.

@mintty
Copy link
Author

mintty commented Jul 25, 2017

@benhillis:

You simply have to set it to your user's default using the wslconfig.exe command line too.

I would certainly prefer a solution without having to tamper with the default setting.
On the other hand, ubuntu ~ does not work; how does bash ~ delegate its ~ parameter to ubuntu? Especially as it cannot really know which default user is configured... Really mysterious.

@zadjii-msft:

by default you should be able to, yes

If you mean "I should be", I agree. But it doesn't work. ubuntu starts in the default user's home directory. ubuntu run ... is a new surprise, it's not documented anywhere. How should anyone know how to configure WSL invocation in a generic manner?

@benhillis, there should be a common approach to this issue. A well-defined interface to run a distribution (and not necessarily the default one) and start in either a selected (or current) or the home directory.

@zadjii-msft
Copy link
Member

@mintty

migrie@MIGRIE-DESKTOP>ubuntu help
Launches or configures a linux distribution.

Usage:
    <no args>
      - Launches the distro's default behavior. By default, this launches your default shell.

    run <command line>
      - Run the given command line in that distro, using the default configuration.
      - Everything after `run ` is passed to the linux LaunchProcess call.

    config [setting [value]]
      - Configure certain settings for this distro.
      - Settings are any of the following (by default)
        - `--default-user <username>`: Set the default user for this distro to <username>

    clean
      - Uninstalls the distro. The appx remains on your machine. This can be
        useful for "factory resetting" your instance. This removes the linux
        filesystem from the disk, but not the app from your PC, so you don't
        need to redownload the entire tar.gz again.

    help
      - Print this usage message.

@sunilmut
Copy link
Member

@zadjii-msft - I agree that there should be some common way of dealing with this and hopefully not a very distro specific thing. Also, is there any way we can improve the usage text, specifically Everything after run is passed to the linux LaunchProcess call.? As an end user, what do I know about LaunchProcess or why should I care about it?

@mintty
Copy link
Author

mintty commented Jul 26, 2017

@zadjii-msft, thanks for the info but it doesn't really help with the use case; who guarantees that each distro will have a run parameter, or even just a help parameter?

@therealkenc
Copy link
Collaborator

therealkenc commented Jul 26, 2017

Both ubuntu.exe and opensuse-42.exe spit out the exact same help, but differ in size by around 30k (ie they're different). Which means, I think, someone is cutting and pasting source code we haven't seen. If that's right and I'm not misinterpreting things, "boo".

@therealkenc
Copy link
Collaborator

therealkenc commented Jul 26, 2017

@mintty - it looks like the CLI parameters to wsl.exe are like this:

C:\WINDOWS\system32\wsl.exe {E23840CC-DC7B-451F-9B14-28300D1474B7} ~ 

So, best I can tell, %localappdata%\Microsoft\WindowsApps\ubuntu.exe is dead weight from wslbridge's standpoint. The run command line parameter to ubuntu.exe spawns wsl.exe. You don't need to destructively tamper with wslconfig. Forget you ever heard the words "execution alias". You just need the magic LxUID (or whatever you call it). Until someone explains otherwise, anyway.

@benhillis
Copy link
Member

@therealkenc - I'll defer to @zadjii-msft since he owns the distribution launcher code.

@zadjii-msft
Copy link
Member

@therealkenc they most certainly are different exe's. I don't know how exactly they differ from one another, but they do set up their initial user differently, so that's something.

@mintty There is no guarantee that every distro will have such a param, as the launcher is ultimately under their control.

I'd agree that wsl <guid> or wsl {guid} ~ is probably a better way for what I know your use case to be.

ubuntu run <commandline> is a nice invocation for other users to intuitively call a particular commandline for a particular distro (certainly more legible than wsl.exe {E23840CC-DC7B-451F-9B14-28300D1474B7} echo foo)

@rprichard
Copy link

FWIW, it'd be nice if we had a precise description of how the command-line from bash.exe, wsl.exe, and ubuntu.exe run is eventually turned into a Linux argument vector.

Here's what I think is going on (as of 10.0.16232.1000):

GetCommandLine WSL execv arg vector
"bash.exe " + CmdLine ["/bin/bash", "-c", "/bin/bash " + CmdLine]
"wsl.exe " + CmdLine ["/bin/bash", "-c", CmdLine]
"ubuntu.exe run " + CmdLine CmdLine is split into argc/argv for MSVCRT [w]main(), then joined with spaces for an argv of ["/bin/bash", "-c", " ".join(MSArgSplit(CmdLine))]

The ubuntu.exe run case is the strangest one, because AFAICT it's the only one that involves ordinary Windows-style command line splitting (e.g. CommandLineToArgvW). I don't think it actually uses CommandLineToArgvW, though -- it behaves more like MSVCRT's startup:

  • ubuntu run echo "1   2" ==> echoes 1 2
  • ubuntu run A="B sh" -c 'echo A=$A' ==> echoes A=B
  • ubuntu run echo "a\\\\"c ==> echoes a\c
  • ubuntu run echo "a\\\\b"c ==> echoes a\\bc
  • ubuntu run echo 1""""""2 ==> echoes 12
  • ubuntu run echo "1""""""2" ==> error: unexpected EOF looking for ". This case demonstrates how ubuntu run uses MSVCRT arg splitting rather than CommandLineToArgvW. CommandLineToArgvW turns "1""""""2" into [1""2], but MSVCRT turns it into [1"""2].

Is the ubuntu.exe run behavior intentional?

Currently, wslbridge invokes bash.exe. I have a tentative change where it would invoke wsl.exe with a GUID. wslbridge wraps arguments with single quotes to avoid shell interpretation. The wslbridge Cygwin frontend passes an argument vector to its WSL backend, so it could use an arbitrary encoding.

@skylize
Copy link

skylize commented Sep 4, 2017

@shevegen

Good documentation would be very helpful here but I am sure that once features/functionality work as designed, documentation will also be provided.

😃What makes you so sure of that? Documentation is a completely different animal than designing features. (And docs are typically much easier to write well along the way, rather than waiting until massive changes to a code base are complete.)

Features can only work as designed. The tricky part is actually designing them as intended. 😃😃😃

@fpqc
Copy link

fpqc commented Sep 5, 2017

@skylize things are likely already partially documented in private docs (that's how ubuntu and suse released as apps on the windows store). The documentation, however, is for a non-public API. Documentation will become available if/when the API becomes public, I assume. I'm not sure that this particular API will be made public. On the other hand, SuSe accidentally released without stripping debug symbols, so a lot of the API has already been reverse-engineered by @RoliSoft

Check this post: RoliSoft/WSL-Distribution-Switcher#50 (comment)

@mintty
Copy link
Author

mintty commented Oct 26, 2017

Thanks; actually the registry is a more reliable source (as referring to the actual system deployment).
Mintty 2.8.0 meanwhile retrieves this information so you can simply call it like mintty --WSL=Ubuntu.
The WSLtty 1.8.0 package also make use of this capability and provides launch icons, context menu entries etc. for all installed distributions.

@bitcrazed
Copy link
Contributor

"There needs to be transparent information about the WSL installation that exist on the system (or for the user), and how to invoke each of them, and which icon to use for it."

I have an idea about how we can make this MUCH easier. Bear with ;)

@ljani
Copy link

ljani commented May 3, 2018

I wonder if I could (ab)use that same reparse point for adding aliases for traditional third-party apps? Currently the reparse point seems to contain the package family name and application id, but is there any way around to that?

For example I'd like to alias %localappdata%\Microsoft\WindowsApps\ps.exe to C:\Program Files\PowerShell\6.0.2\pwsh.exe.

I tried to dig this, but didn't get really far. It seems ApiSetHost.AppExecutionAlias.dll is responsible for reading the reparse point.

EDIT: Obviously I tried to just change the exe path stored in the metadata, but that didn't work.

@Biswa96
Copy link

Biswa96 commented May 3, 2018

@ljani You can add CreateProcess() in C/C++ or Process.Start() in C# functions in WindowsApps\ps.exe to start pwsh.exe.

@ljani
Copy link

ljani commented May 3, 2018

@Biswa96 If you mean writing a separate wrapper program, then yes, that's what I'm doing now, but it's not perfect (for example, obscure bug with the standard streams and SIGINT). I'd much prefer if the trampoline was not there, and the correct process was launched directly.

@benhillis
Copy link
Member

Discussion has run its course. Also in recent insider builds a "-d, --distribution" flag was added to wsl.exe to specify a specific distribution to launch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests