Rust PowerShell脚本执行库powershell_script的使用,支持在Rust中无缝运行和管理PowerShell命令与脚本

Rust PowerShell脚本执行库powershell_script的使用

基本介绍

powershell_script是一个基础的Rust库,它使用std::process::Command将命令传递给PowerShell,并提供了对process::Output的便捷包装器,特别适合在Rust中运行Windows PowerShell命令。

基础使用方法

建议将PowerShell命令写入.ps文件中,这样可以更好地利用现有工具创建和维护脚本。

示例1:创建桌面快捷方式

PowerShell脚本文件 (script.ps)

$SourceFileLocation="C:\Windows\notepad.exe"
$ShortcutLocation=[Environment]::GetFolderPath("Desktop")+"\notepad.lnk"
$WScriptShell=New-Object -ComObject WScript.Shell
$Shortcut=$WScriptShell.CreateShortcut($ShortcutLocation)
$Shortcut.TargetPath=$SourceFileLocation
$Shortcut.Save()

Rust代码 (main.rs)

use powershell_script;

fn main() {
    // 包含PowerShell脚本文件内容
    let create_shortcut = include_str!("script.ps");
    
    // 运行脚本并处理结果
    match powershell_script::run(create_shortcut) {
        Ok(output) => {
            println!("{}", output);
        }
        Err(e) => {
            println!("Error: {}", e);
        }
    }
}

高级控制 - 使用PsScriptBuilder

PsScriptBuilder提供了更多配置选项来控制PowerShell脚本的执行方式。

示例2:使用PsScriptBuilder配置执行选项

use powershell_script::PsScriptBuilder;

fn main() {
    // 创建PowerShell脚本构建器并配置选项
    let ps = PsScriptBuilder::new()
        .no_profile(true)      // 不加载用户配置文件
        .non_interactive(true) // 非交互模式
        .hidden(false)         // 不隐藏窗口
        .print_commands(false) // 不打印执行的命令
        .build();
    
    // 执行简单命令
    let output = ps.run(r#"echo "hello world""#).unwrap();

    // 验证输出
    assert!(output.stdout().unwrap().contains("hello world"));
}

完整示例代码

示例3:获取系统进程信息

use powershell_script::PsScriptBuilder;

fn get_process_info() {
    // 创建配置好的PowerShell执行器
    let ps = PsScriptBuilder::new()
        .no_profile(true)
        .build();
    
    // 执行获取进程信息的命令
    let output = ps.run(r#"
        Get-Process | 
        Select-Object -Property ProcessName, Id, CPU | 
        ConvertTo-Json -Compress
    "#).unwrap();
    
    // 解析JSON输出
    if let Ok(processes) = serde_json::from_str::<Vec<serde_json::Value>>(output.stdout().unwrap()) {
        for process in processes {
            println!("进程: {}, ID: {}, CPU使用: {}", 
                process["ProcessName"].as_str().unwrap(),
                process["Id"].as_u64().unwrap(),
                process["CPU"].as_f64().unwrap());
        }
    }
}

示例4:系统服务管理

use powershell_script;

fn manage_services() {
    // 直接运行多行PowerShell命令
    let commands = r#"
        # 获取所有运行中的服务
        $running = Get-Service | Where-Object { $_.Status -eq 'Running' }
        
        # 输出服务数量
        Write-Output "当前有 $($running.Count) 个服务正在运行"
        
        # 获取前5个服务详细信息
        $running | Select-Object -First 5 | Format-Table -AutoSize
    "#;
    
    match powershell_script::run(commands) {
        Ok(output) => {
            println!("服务信息:\n{}", output);
        }
        Err(e) => {
            eprintln!("获取服务信息失败: {}", e);
        }
    }
}

功能特点

  1. 跨平台支持

    • Windows: 默认使用系统自带的PowerShell,也可通过core功能使用PowerShell Core
    • 其他操作系统: 使用PowerShell Core运行脚本
  2. 灵活的脚本执行方式

    • 支持从文件加载脚本
    • 支持直接执行字符串命令
    • 支持多行命令执行
  3. 丰富的输出处理

    • 提供对stdout/stderr的便捷访问
    • 支持错误处理和状态检查
  4. 执行控制选项

    • 控制是否加载用户配置文件(no_profile)
    • 设置交互模式(non_interactive)
    • 控制窗口显示(hidden)
    • 调试输出(print_commands)

使用建议

  1. 对于复杂脚本,建议保存在单独的.ps文件中
  2. 使用PsScriptBuilder配置执行环境,特别是生产环境
  3. 处理输出时考虑使用JSON格式以便于解析
  4. 注意错误处理,特别是跨平台使用时

1 回复

Rust PowerShell脚本执行库 powershell_script 使用指南

powershell_script 是一个 Rust 库,允许开发者在 Rust 程序中无缝执行和管理 PowerShell 命令与脚本。它提供了简单易用的 API 来运行 PowerShell 命令并获取结果。

安装

Cargo.toml 中添加依赖:

[dependencies]
powershell_script = "1.0"

基本用法

执行简单命令

use powershell_script::PsScriptBuilder;

fn main() {
    // 定义要执行的PowerShell命令
    let cmd = "Get-Process | Select-Object -First 3";
    
    // 构建并执行PowerShell脚本
    let output = PsScriptBuilder::new()
        .no_profile(true)       // 不加载用户配置文件
        .non_interactive(true)  // 非交互模式
        .hidden(false)          // 不隐藏窗口
        .print_commands(false)  // 不打印执行的命令
        .build()
        .run(cmd)
        .unwrap();
    
    // 输出执行结果
    println!("Status: {}", output.status.success());
    println!("Stdout: {}", output.stdout());
    println!("Stderr: {}", output.stderr());
}

执行脚本文件

use powershell_script::PsScriptBuilder;

fn main() {
    // 执行指定的PowerShell脚本文件
    let output = PsScriptBuilder::new()
        .run_from_file("script.ps1")
        .unwrap();
    
    // 输出脚本执行结果
    println!("Script output: {}", output.stdout());
}

高级功能

传递参数

use powershell_script::{PsScriptBuilder, EscapePowerShellArg};

fn main() {
    // 安全转义参数
    let param1 = "Hello".escape_powershell_arg();
    let param2 = "World".escape_powershell_arg();
    
    // 构建带参数的PowerShell命令
    let cmd = format!("param($p1, $p2) Write-Output \"$p1 $p2\" -args {}, {}", param1, param2);
    
    // 执行命令
    let output = PsScriptBuilder::new()
        .run(&cmd)
        .unwrap();
    
    println!("Output: {}", output.stdout());
}

异步执行

use powershell_script::PsScriptBuilder;
use tokio::runtime::Runtime;

fn main() {
    // 创建Tokio运行时
    let rt = Runtime::new().unwrap();
    
    // 异步执行PowerShell命令
    let output = rt.block_on(async {
        PsScriptBuilder::new()
            .run_async("Get-Service | Where-Object { $_.Status -eq 'Running' }")
            .await
    }).unwrap();
    
    println!("Running services:\n{}", output.stdout());
}

处理二进制输出

use powershell_script::PsScriptBuilder;

fn main() {
    // 执行生成二进制数据的命令
    let output = PsScriptBuilder::new()
        .run("[System.Text.Encoding]::UTF8.GetBytes('Binary data')")
        .unwrap();
    
    // 获取二进制输出
    let binary_data = output.stdout_bytes();
    println!("Binary data length: {}", binary_data.len());
}

错误处理

use powershell_script::{PsScriptBuilder, PowerShellError};

fn main() -> Result<(), PowerShellError> {
    // 尝试执行不存在的命令
    let output = PsScriptBuilder::new()
        .run("This-Command-Does-Not-Exist")?;
    
    // 检查命令是否执行成功
    if !output.status.success() {
        eprintln!("PowerShell error: {}", output.stderr());
    }
    
    Ok(())
}

完整示例

下面是一个结合了多个功能的完整示例:

use powershell_script::{PsScriptBuilder, EscapePowerShellArg};
use tokio::runtime::Runtime;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 示例1: 执行简单命令
    println!("=== 示例1: 执行简单命令 ===");
    let cmd = "Get-ChildItem | Select-Object -First 5";
    let output = PsScriptBuilder::new()
        .no_profile(true)
        .non_interactive(true)
        .run(cmd)?;
    println!("Command output:\n{}", output.stdout());

    // 示例2: 传递参数
    println!("\n=== 示例2: 传递参数 ===");
    let user = "Admin".escape_powershell_arg();
    let message = "Welcome!".escape_powershell_arg();
    let param_cmd = format!(
        "param($user, $msg) Write-Output \"User: $user, Message: $msg\" -args {}, {}",
        user, message
    );
    let param_output = PsScriptBuilder::new().run(&param_cmd)?;
    println!("Parameter output: {}", param_output.stdout());

    // 示例3: 异步执行
    println!("\n=== 示例3: 异步执行 ===");
    let rt = Runtime::new()?;
    let async_output = rt.block_on(async {
        PsScriptBuilder::new()
            .run_async("Get-Date -Format 'yyyy-MM-dd HH:mm:ss'")
            .await
    })?;
    println!("Current date: {}", async_output.stdout());

    // 示例4: 错误处理
    println!("\n=== 示例4: 错误处理 ===");
    match PsScriptBuilder::new().run("Non-Existent-Cmdlet") {
        Ok(output) => {
            if !output.status.success() {
                println!("Command failed with error: {}", output.stderr());
            }
        }
        Err(e) => println!("Execution error: {}", e),
    }

    Ok(())
}

注意事项

  1. 在 Windows 上需要安装 PowerShell
  2. 在非 Windows 平台上需要安装 PowerShell Core (pwsh)
  3. 对于敏感命令,考虑使用 .hidden(true) 来隐藏 PowerShell 窗口
  4. 使用 .escape_powershell_arg() 方法来安全地传递参数,防止注入攻击

这个库为 Rust 和 PowerShell 之间的互操作提供了强大的支持,特别适合需要在 Rust 应用中集成 Windows 管理功能的场景。

回到顶部