I'm building a tauri desktop app around tshark and want to call out to the cli in Rust and pipe results back to the UI (svelte).
THis is my main.rs
in tauri:
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]use std::process::Stdio;use tauri::Manager;use tokio::io::{AsyncBufReadExt, BufReader};use tokio::process::Command; // Ensure this is actually used elsewhere, or remove it.#[tauri::command]fn greet(name: &str) -> String { format!("Hello, {}!", name)}// Define the function that starts tshark and captures its output#[tauri::command]// Use async function and pass the Tauri AppHandleasync fn start_tshark(app: tauri::AppHandle) -> Result<(), String> { let mut child = Command::new("sudo") .args(["tshark", "-i", "any"]) .stdout(Stdio::piped()) .spawn() .map_err(|e| e.to_string())?; let stdout = child.stdout.take().ok_or("Failed to capture stdout")?; let reader = BufReader::new(stdout); let mut lines = reader.lines(); let main_window = app.get_window("main").ok_or("Main window not found")?; while let Ok(Some(line)) = lines.next_line().await { if let Err(e) = main_window.emit("tshark-output", &line) { return Err(e.to_string()); } } // Correctly await the completion of the child process if let Err(e) = child.wait().await { return Err(format!("Tshark process failed: {}", e)); } Ok(())}fn main() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![start_tshark, greet]) .run(tauri::generate_context!()) .expect("error while running tauri application");}
and this is my client side listener in svelte:
<script> import { onMount, onDestroy } from "svelte"; import { invoke } from "@tauri-apps/api/tauri"; import { listen } from "@tauri-apps/api/event"; import Greet from "../components/Greet.svelte"; let unlisten; // To hold the function to unlisten to events onMount(() => { const startBtn = document.getElementById("start-tshark"); const output = document.getElementById("output"); startBtn.onclick = async () => { try { const res = await invoke("start_tshark"); // Set up the event listener unlisten = await listen("tshark-output", (event) => { console.log("Received from Rust:", event.payload); output.textContent = event.payload; }); } catch (err) { output.textContent = err; } }; }); // Ensure to clean up the event listener when the component is destroyed onDestroy(() => { if (unlisten) { unlisten(); } });</script><button id="start-tshark">Start Tshark</button><button id="stop-tshark">Stop Tshark</button><pre id="output"></pre><Greet />
I don't get anymore compile errors, but the UI just hangs, I see the backend is calling tshark and logging output but nothing gets sent to the frontend.