Rust Command::new Windows raw_args

I need to use Start-Process in an exe to call itself so that when called part of the app has elevated permissions. I was using env::current_exe().unwrap(); the problem is that for whatever reason Command is not unescaping the file path when passed to .args(&[...])

The expected command must look like Start-Process 'C:\path\from\env::current_exe().unwrap()' -Verb RunAs -ArgumentList 'arg1' 'arg2'

Ive found raw_args CommandExt in std::os::windows::process - Rust but :

This trait is sealed: it cannot be implemented outside the standard library. This is so that future additional methods are not breaking changes.

lets assume this is the function

fn call_self(){
    let file_path = env::current_exe().unwrap();

    let path_str = file_path.as_str().unwrap();

    let _ = Command::new("Start-Process")
        .args(&[path_str, "-Verb", "RunAs"])
        .spawn()
        .expect("failed to execute process");
}

Any other ideas??

I believe path_str should be to_str() and not as_str()?

Also, Start-Process is a powershell command, not a .exe, right? So you'll need to run powershell first. So something like:

fn call_self(){
    let file_path = env::current_exe().unwrap();

    let path_str = file_path.as_str().unwrap();

    let _ = Command::new("powershell.exe")
        .args(&["-Command", "Start-Process", path_str, "-Verb", "RunAs"])
        .spawn()
        .expect("failed to execute process");
}

Ty for the reply :slight_smile: I tried that but was given a powershell error saying RunAs wasnt a valid param... any other ideas

Sorry no, I'm out of ideas. This test program is working for me so I don't know:

Test program
use std::{env, process::Command};

fn main(){
    let file_path = env::current_exe().unwrap();

    let path_str = file_path.to_str().unwrap();

    let _ = Command::new("powershell.exe")
        .args(&["-Command", "Start-Process", path_str, "-Verb", "RunAs"])
        .spawn()
        .expect("failed to execute process");
}

For what it’s worth, the PowerShell code will end up calling ShellExecute, which might be easier to use directly if the quoting is getting you down:

let cmd: Vec<u16> = env::current_exe().unwrap().as_os_str().encode_wide().collect();
let cmd = HSTRING::from_wide(&cmd).unwrap();
let r = unsafe {
    ShellExecuteW(HWND(0), w!("runas"), &cmd, PCWSTR::null(), PCWSTR::null(), SW_NORMAL)
};
if r.0 <= 32 {
    println!("error: {:?}", Error::from_win32());
}

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.