std::process::Command documentation examples do not work

hello, been searching for other std::process::Command solutions - however can't seem to find a solution.

Is anyone else having problems running basic command line programs using this? Not even the examples located here compile / work properly.

I'm trying to export a registry hive in windows ... basically "cmd reg export "HKEY_CURRENT_USER..." "target location"...

Or should I just go and do this in C# lol

Please post your actual code and the error(s) you get, it's impossible to say anything with no more information than "doesn't work properly".

2 Likes

Hello,

Thanks for the reply... tried the following:

use std::process::Command;

fn main() {


let output = if cfg!(target_os = "windows") {
    Command::new("cmd")
            .args(&["/C", "echo hello"])
            .output()
            .expect("failed to execute process")
} else {
    Command::new("sh")
            .arg("-c")
            .arg("echo hello")
            .output()
            .expect("failed to execute process")
};

let hello = output.stdout;
println!("asdfasdf")

}

It prints asdfasdf fine, but doesn't echo anything even when running the exe from an open CMD prompt.

thanks,

You're not actually doing anything with the output in that code, other than assigning it to a variable. hello is a Vec<u8> containing the output - you'll could either convert it to a string:

use std::process::Command;
use std::str;

fn main() {
    let output = if cfg!(target_os = "windows") {
        Command::new("cmd")
            .args(&["/C", "echo hello"])
            .output()
            .expect("failed to execute process")
    } else {
        Command::new("sh")
            .arg("-c")
            .arg("echo hello")
            .output()
            .expect("failed to execute process")
    };

    let hello = output.stdout;
    let hello2 = str::from_utf8(&hello).unwrap();
    println!("{}", hello2);
}

Or you could write it directly to the parent process' stdout:

use std::process::Command;
use std::io::prelude::*;
use std::io;

fn main() {
    let output = if cfg!(target_os = "windows") {
        Command::new("cmd")
            .args(&["/C", "echo hello"])
            .output()
            .expect("failed to execute process")
    } else {
        Command::new("sh")
            .arg("-c")
            .arg("echo hello")
            .output()
            .expect("failed to execute process")
    };

    io::stdout().write_all(&output.stdout).unwrap();
}
1 Like

hmmm ok that seems to work, but what about if the Command::new("cmd") is meant to run args to export registry subkey? e.g. .args(&["/C", "reg export", r#"HKEY_CURRENT_USER\Software\\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles" "c:\testcode\test.reg"#])

I don't know just trying to hash up something quick that'll export registry, read the export find specific server details in it, modify it and then reimport when launchin exe.

Without Windows here, but it looks like "reg" and "export" should be two arguments, not one? That, or the whole command for /C could be required as a single argument.

Tried the following three variations... none of which works:

        Command::new("cmd")
        .args(&["/C", "reg", "export", r#"HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles" "c:\2020\test.reg"#])

//**********************

        Command::new("cmd")
        .args(&[r#"/C reg export "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles" "c:\2020\test.reg"#])

//**********************
Command::new("cmd")
.args(&[r#"reg export "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles" "c:\2020\test.reg"#])

So typically on Windows CMD, the following can be run which does the export
reg export "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles" "C:\2020\coding\test.reg"

I overlooked that before, but in the first version the key and filename are still in one argument and should be two.

The second one is missing the final quote after test.reg.

Otherwise, we'll have to wait for someone with Windows to test it out.

hmmm yeah you're right... but tried the following and still no joy:

        Command::new("cmd")
        .args(&["/C", "reg", "export", r#""HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles""#, r#""c:\2020\test.reg""#])

Seeing that even in the command prompt (cmd) the registry path and the target path both require double quotes around them for it to work.

Also the following didn't work either:
Command::new("cmd").args(&[r#"reg export "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles" "c:\2020\test.reg""#])

Thanks for your help anyway - very prompt responses - wasn't expecting any responses for at least a week lol

Why do you use cmd /C ...? In the example of echo hello, the cmd /C is needed because echo is not an executable named echo.exe, but a built-in functionality of cmd.exe. So cmd.exe has to be called with an argument telling it to execute the built-in function echo.
If you run another command using cmd /C, I think you need to have the argument as one long string, because cmd.exe itself splits the string at the whitespaces to supply individual arguments to the called command. So you could use

Command::new("cmd")
.args(&["/C", r#""reg export "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles" c:\2020\test.reg""#]).output().unwrap();

BUT, as you don't call a built-in function of cmd.exe, but a standalone reg.exe, you should rather call it directly without cmd.exe:

Command::new("reg")
.args(&["export", r"HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles", r"c:\2020\test.reg"]).output().unwrap();

In this call, you have to separate your arguments by putting them in individual &strs in the args vector,
because there is no cmd.exe to do the "split at whitespace" step.

6 Likes

Awesome thanks @csam your tip worked. The following exported as required.

Command::new("reg.exe")
        .args(&["export", "\"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles", "c:\\2020\\test.reg"])

What a great community Rust has!

3 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.