pty icon indicating copy to clipboard operation
pty copied to clipboard

Support Windows through `conpty`

Open hinshun opened this issue 5 years ago • 23 comments
trafficstars

Windows 10 gained support for psuedo-terminals with conpty: https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/

Prior art:

  • node-pty: https://github.com/nodejs/node/blob/b3189266347fa05395860f9f6e8949e447977284/test/pseudo-tty/pty_helper.py
  • neovim: https://github.com/neovim/neovim/pull/11390

Would you be open to a PR?

hinshun avatar Apr 30 '20 05:04 hinshun

Having windows support would be great.

PRs are welcome indeed :)

On Thu, Apr 30, 2020 at 1:29 AM Edgar Lee [email protected] wrote:

Windows 10 gained support for psuedo-terminals with conpty: https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/

Prior art:

Would you be open to a PR?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/creack/pty/issues/95, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAD7LZNURJEB7ZAQFBT77DLRPEEDXANCNFSM4MVF3YSA .

--

Guillaume J. Charmes Software Engineer https://blog.charmes.net [image: Guillaume J. Charmes on about.me] https://blog.charmes.net

creack avatar Apr 30 '20 11:04 creack

Another option would be to use go-winpty but is based of winpty.dll.

You can also look at the source of portable-pty from rust that supports both winpty and conpty.

prabirshrestha avatar May 23 '20 17:05 prabirshrestha

I noted in #50 that https://github.com/containerd/console has a console implementation for Windows. There's quite a bit of overlap with this library -- so it might be worth borrowing from that if someone were to open a PR.

virtuald avatar Jun 22 '20 17:06 virtuald

Any update on this? Would be so great to see this happen

liuhaowen478 avatar Oct 15 '20 01:10 liuhaowen478

ActiveState implemented a Go library for conpty: termtest/conpty

mardukbp avatar Nov 13 '20 15:11 mardukbp

@mardukbp unfortunatelly termtest/conpty is based on CGO, which is not an option here as it would be a breaking change. We could consider it for a v2 though.

@virtuald This looks interesting indeed, but as I have 0 experience with windows, I have no idea what's going on there.. If someone want to create a PR, I'd be happy to bring it in, but I don't think I'll have time to do it myself anytime soon.

@liuhaowen478 We are looking for motived people to contribute :)

creack avatar Nov 24 '20 14:11 creack

@creack How do you know that termtest/conpty is based on CGO? As far as I can tell, it uses the syscall and windows go packages. I could not find any reference to cgo in the code.

mardukbp avatar Nov 24 '20 17:11 mardukbp

As I have no experience with windows, I might be wrong and I didn't test it, but I saw this: https://github.com/ActiveState/termtest/blob/master/conpty/syscall_windows.go#L16

AFAIK, loading a plugin in go requires cgo (golang/go#19569)

creack avatar Nov 25 '20 15:11 creack

For what it's worth, here's what I get on a Windows machine:

User@Desktop MINGW64 ~/go/src
$ CGO_ENABLED=0 go get github.com/ActiveState/termtest

User@Desktop MINGW64 ~/go/src
$ cd github.com/ActiveState/termtest/conpty/cmd/example

User@Desktop MINGW64 ~/go/src/github.com/ActiveState/termtest/conpty/cmd/example (master)
$ CGO_ENABLED=0 go build

User@Desktop MINGW64 ~/go/src/github.com/ActiveState/termtest/conpty/cmd/example (master)
$ ./example.exe
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS C:\Users\User\Downloads> echo "hello world"
hello world
PS C:\Users\User\Downloads>
exit code was: 0

AlbinoDrought avatar Nov 25 '20 17:11 AlbinoDrought

According to the Go Wiki loading a DLL with syscall does not require cgo.

AFAIK, loading a plugin in go requires cgo (golang/go#19569)

Yes, but termtest/conpty does not use go plugins.

I think this library is good to go! 😉

mardukbp avatar Nov 25 '20 17:11 mardukbp

Hi @creack , I have opened a pull request for windows conpty support (#109 ), but as noted as known issues there, I probably need some guidance to solve these issues since I am not a windows expert, any idea?

ghost avatar Nov 30 '20 12:11 ghost

@jeffreystoke I'll take a look this week, thanks for the pr!

creack avatar Nov 30 '20 22:11 creack

Has there been any progress on the ConPTY support for Windows so far? I noticed that this PR is still not merged.

imbytecat avatar Oct 12 '21 11:10 imbytecat

Not yet. concerns about breaking change and overall usability issue. I haven't yet been able to get this to work on my windows machine.

creack avatar Oct 13 '21 14:10 creack

I think we fixed a lot of usability issues. I have tested it with powershell.

var f pty.Pty
var err error

f, err = pty.Start(exec.Command("powershell"))
if err != nil {
	return nil, err
}

photostorm avatar Oct 13 '21 16:10 photostorm

@photostorm How did you getting it working? I have the following code:

func main() {
	var f pty.Pty
	var err error

	f, err = pty.Start(exec.Command("cmd"))
	if err != nil {
		log.Fatal(err)
	}

	defer f.Close()

	h := f.Fd()

	oldState, err := term.MakeRaw(int(h))
	if err != nil {
		panic(err)
	}
	defer func() { _ = term.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.

	go func() { _, _ = io.Copy(f, os.Stdin) }()
	_, _ = io.Copy(os.Stdout, f)
}

output:

panic: The handle is invalid.

goroutine 1 [running]:
main.main()
        C:/repos/work/github.com/jeffreystoke/pty/test/test.go:69 +0x1eb
exit status 2

I can't seem to get a proper windows handle.

== EDIT:RESOLVED ==

I should have used os.Std.Fd() instead of f.Fd(). My bad. I have it working in Windows now.

jherman avatar Oct 13 '21 19:10 jherman

@jherman

Glad you have made it working, just comment for others may have the same issue:

term.MakeRaw

If you mean golang.org/x/sys/term.MakeRaw, that's meant for windows console, not conpty.

ref:

  • MakeRaw: https://cs.opensource.google/go/x/term/+/03fcf44c:term_windows.go;l=23
  • Windows Console API: https://docs.microsoft.com/en-us/windows/console/console-reference

ghost avatar Oct 14 '21 11:10 ghost

@creack any chance to test it again? I'm pretty confident it works now.

ghost avatar Oct 14 '21 11:10 ghost

@jeffreystoke Thanks for the reply. I was able to make it work using the sample code in the readme, with only commenting out the section involving resize of the console. I still haven't found a good way to resize the console by listening for some event vs an inefficient polling for a size change.

I did find an issue with running interactive console UI's like FAR manager. You can't navigate or pretty much do anything with the function keys. This does work on the *nix bash sessions. Can you confirm if it's just me? If so, can you provide a working sample?

For those interested in the code I used:

package main

import (
	"io"
	"log"
	"os"
	"os/exec"

	"github.com/creack/pty"
	"golang.org/x/term"
)

func test() error {
	// Create arbitrary command.
	c := exec.Command("powershell")

	// Start the command with a pty.
	ptmx, err := pty.Start(c)
	if err != nil {
		return err
	}
	// Make sure to close the pty at the end.
	defer func() { _ = ptmx.Close() }() // Best effort.

	// Set stdin in raw mode.
	oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
	if err != nil {
		panic(err)
	}
	defer func() { _ = term.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.

	// Copy stdin to the pty and the pty to stdout.
	// NOTE: The goroutine will keep reading until the next keystroke before returning.
	go func() { _, _ = io.Copy(ptmx, os.Stdin) }()
	_, _ = io.Copy(os.Stdout, ptmx)

	return nil
}

func main() {
	if err := test(); err != nil {
		log.Fatal(err)
	}
}

jherman avatar Oct 14 '21 14:10 jherman

@jherman

You can't navigate or pretty much do anything with the function keys.

Looks like a terminal escape sequence translation issue, result from my quick search suggests you should turn on or off the translation depending on your terminal emulator implementation. (windows.SetConsoleMode(handle, state | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING))

Ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences

ghost avatar Oct 14 '21 15:10 ghost

@creack I know it been a couple months, but what are the tasks you would like done for windows support for it to be merge. I can continue PR.

photostorm avatar Feb 06 '22 01:02 photostorm

Can I use it on Windows?

geekroscom avatar Jan 14 '23 11:01 geekroscom