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

Drag & Drop from File Explorer produces incorrect file paths with WSL #331

Closed
acesnik opened this issue Dec 19, 2018 · 11 comments · Fixed by #11625
Closed

Drag & Drop from File Explorer produces incorrect file paths with WSL #331

acesnik opened this issue Dec 19, 2018 · 11 comments · Fixed by #11625
Labels
Area-Interaction Interacting with the vintage console window (as opposed to driving via API or hooks) Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Conhost For issues in the Console codebase Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.

Comments

@acesnik
Copy link

acesnik commented Dec 19, 2018

Dragging & dropping a file from Windows File Explorer into a Bash window produces the path formatted for Windows instead of Ubuntu.

Dragging the Desktop folder into a Bash window should produce the text /mnt/c/Users/acesnik/Desktop. Instead, it produces C:\Users\acesnik\Desktop.

Your Windows build number
Edition: Windows 10 Pro
Version: 1607
OS Build: 14393.576

See also microsoft/WSL#1501

@acesnik acesnik changed the title Drag & Drop from File Explorer produces incorrect file paths Drag & Drop from File Explorer produces incorrect file paths with WSL Dec 19, 2018
@zadjii-msft zadjii-msft added Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. backlog Product-Conhost For issues in the Console codebase labels Dec 19, 2018
@zadjii-msft
Copy link
Member

There's not really a way for us as the console/terminal to be able to know what format the shell running attached to us wants the path in. I wouldn't even begin to know how to begin implementing this.

I've filed MSFT:19977636 to track this request, but I don't think it's going to go anywhere any time soon, especially without any plan for how it'd be possible.

@zadjii-msft zadjii-msft added this to the Backlog milestone Dec 19, 2018
@therealkenc
Copy link

therealkenc commented Dec 20, 2018

I wouldn't even begin to know how to begin implementing this.

Thanks Mike. Since I'm the one who rudely punted here, I should probably speak up. That wasn't the answer I expected, but I understand the answer. WSL (on its end of the pty) has no business knowing what you are doing when a file is dropped onto your window. On your end of the pty, you are saying (point blank): hey I have no idea how WSL wants that path string to look. I don't even know it is WSL.

Impasse.

The popular competing terminal emulator implements this by throwing out separation of concerns. The emulator knows the context of the thing that launched it (historically that meant Cygwin). You can do the same. So for wsl.exe context might be the string "wsldistro=Ubuntu1804" and then way up in your drop handler you do a bunch of dirty work (which your terminal emulator really has no business knowing) to convert the path. For powershell.exe the context string would be, well, nothing. The details of that dirty work doesn't matter for our purposes right now. You probably don't like that answer, but at least this is a different answer than "there's not any way for us ...to know".

The other way to do this is inversion of control. You provide a hook, which wsl.exe (or powershell.exe or cmd.exe) can consume. How you'd provide that inter-process hook is up to you, but at least the signature is conceptually bog simple. Method OnPathDrop takes a string and returns a string. Framing the problem this way means you don't have to know the dirty details, ever. Not your problem. The scope of work is providing said hook.

Academic, I know. Beats empty proposition.

@HBelusca
Copy link
Contributor

HBelusca commented Dec 21, 2018

There's not really a way for us as the console/terminal to be able to know what format the shell running attached to us wants the path in. I wouldn't even begin to know how to begin implementing this.

The problem is that the paste is seen by conhost, that will then emulate keypresses to be sent to the underlying console application. I would suppose that in the WSL it's either wsl.exe or bash.exe (??) and they would have to detect that the thing you are entering at this precise moment is a file path (rather than "random" keypresses), and then do a path conversion "à la Cygwin".

The problem here of course is that detection.

Unless, it is possible, from within conhost, to "detect" whether the console application that has the focus (is the main) in the given console, will expect *nix-type file paths instead of win32-type file paths.
If this was possible, then a win32 to *nix file path conversion would have to take place in conhost.exe.

An alternative way (that is inspired from Wolfram Mathematica when you paste file paths in a string), would be to recognize that the file path has a certain form, namely "driver_letter:\path\to\file" . If such recognition can be performed, then one can then convert this type of string to a *nix-formatted file path.
Since that solution would be handled by the console application itself, the console app could display some kind of "popup" character-window asking whether or not to perform the file-path conversion.

EDIT: You can check how git-bash / cygwin proceeds. If you paste a win32-formatted path enclosed in quotes, like for example in: cd "C:\Windows", it will transform the path automatically internally into /mnt/c/Windows/ and perform the associated command.
See e.g. https://unix.stackexchange.com/questions/341080/is-there-implicit-path-conversion-in-cygwin , http://www.mingw.org/wiki/Posix_path_conversion

@stevemk14ebr
Copy link

stevemk14ebr commented Jun 26, 2020

Hi, can this please be implemented? It's pretty trivial as far as i can tell, the parent process for conhost is wsl.exe so all it needs to do is check the module name of it's parent process. This can be done a number of ways, the easiest of which is probably just enumerating the processes and checking pids. If one is found get the window name and check for 'wsl.exe': https://gist.github.com/mattn/253013/d47b90159cf8ffa4d92448614b748aa1d235ebe4 (additionally should probably verify the parent start time is before child start time). OR wslhost could simply be modified to pass a handle of itself down to conhost. Either way this is an insanely useful feature.

image

@zadjii-msft
Copy link
Member

zadjii-msft commented Jun 26, 2020

Ah but what if you're running cmd.exe within WSL 🤔

the parent process for conhost is wsl.exe

Well, that's certainly not what I'd expect actually. That's curious that there's an extra console process hanging around when WSL is already attached to a console. In your screenshot, the console server for wsl.exe is actually OpenConsole.exe, presumably 18360.

EDIT: I realized I'm dumb - I'm pretty sure that extra conhost is the one they use as a conpty for Windows interop, which I maybe helped write 🥚->🤕

@stevemk14ebr
Copy link

stevemk14ebr commented Jun 26, 2020

image

wslhost.exe is always the parent of conhost for wsl systems afaik. The wsl.exe is parent of cmd.exe when spawned from within a wsl2 environment. Grab process hacker2 and try for yourself. But since this is all microsoft code the correct solution would be to just have the parent pass a handle to itself down to the child to detect this. This is entirely solvable.

@lachjames
Copy link

lachjames commented Aug 16, 2021

I'd also love this feature - I think it could be implemented with a combination of two options for profiles:

  • DragDropFileSlash: "replace", or "keep" - either replaces the Windows slashes with the Unix ones, or doesn't. Might require some logic to ensure it doesn't mess with escaped characters, but I'm sure it's doable (see, for example, the second solution here https://stackoverflow.com/questions/25146960/python-convert-back-slashes-to-forward-slashes/25146984).
  • DragDropFilePattern: "/mnt/{drive}/{path}" - substitutes {drive} with the drive letter and {path} with the path (after replacing slashes as per DragDropFileSlash). Doesn't need to be a regex, just a simple Python-like format will almost certainly cover all any use case.

This would solve the problem without requiring the terminal to know what's running (except for knowledge of which profile is open, which it already has).

@ghost ghost added In-PR This issue has a related PR and removed In-PR This issue has a related PR labels Oct 27, 2021
@ghost ghost closed this as completed in #11625 Nov 10, 2021
@ghost ghost removed the In-PR This issue has a related PR label Nov 10, 2021
ghost pushed a commit that referenced this issue Nov 10, 2021
Drag and drop does not work for WSL because paths are pasted as windows
paths having incorrect path separator and path root.  This PR adds code
to correct the path in TerminalControl before pasting to WSL terminals.

One problem with this approach is that it assumes the default WSL
automount root of "/mnt". It would be possible to add a setting like
"WslDragAndDropMountRoot"... but I decided it if someone wants to change
automount location it would be simple enough just to create the "/mnt"
symlink in WSL.

## Validation
Couldn't find an obvious place to add a test.  Manually tested
cut-n-paste from following paths:
- "c:\"
- "c:\subdir"
- "c:\subdir\subdir"
- "\\wsl.localhost\<distro>"
- \\wsl.localhost\<distro>\subdir"

Closes #331
@ghost ghost added the Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release. label Nov 10, 2021
@ghost
Copy link

ghost commented Feb 3, 2022

🎉This issue was addressed in #11625, which has now been successfully released as Windows Terminal Preview v1.13.10336.0.:tada:

Handy links:

@Matsuyanagi
Copy link

Has no effect on WSL Ubuntu 22.04.1 LTS.

Ubuntu 22.04.1 LTS installed from the Microsoft Store is configured in this way, so it is not determined correctly.

	"source": "CanonicalGroupLimited.Ubuntu22.04LTS_79rhkp1fndgsc"

ManglePathsForWsl() determines like this.
It has to be a more efficient way of judging or set manually.
/terminal/src/cascadia/TerminalControl/ControlInteractivity.cpp:676

    bool ControlInteractivity::ManglePathsForWsl()
    {
        return _core->Settings().ProfileSource() == L"Windows.Terminal.Wsl";
    }

@DHowett
Copy link
Member

DHowett commented Oct 6, 2022

FWIW, This is an excellent example of why I always thought that pushing the source down into the control layer to make the decision about drag/drop was the wrong thing to do. Hmm.

@Matsuyanagi
Copy link

This feature that automatically converts the dropped file path according to the shell/OS is very convenient.
If it is difficult to determine automatically, it would be nice if a user could add an item to profiles.list[] in the settings.json.

settings.json

    "profiles": 
        "list": 
            {
                "transWslPath": true
                ...
            }

    bool ControlInteractivity::ManglePathsForWsl()
    {
        return _core->Settings().ProfileSource() == L"Windows.Terminal.Wsl" /* || ...Settings.Profile.Something.TransWslPath() */;
    }

#1772 (comment)
I agree this comment, but looking at the source code, it seems like it would be difficult with just a few simple regular expressions.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Interaction Interacting with the vintage console window (as opposed to driving via API or hooks) Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Conhost For issues in the Console codebase Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants