I’m writing a small utility to get the PID of a process based upon its name. I’ve started the implementation by writing the Windows version which is fairly simple and makes use of the winapi
crate. The code looks as follows so far (yes, the return type will be Result<>
, rather than Option<>
, it’s just easier to test optionals whilst I’m working out the logic):
extern crate winapi;
extern crate kernel32;
use kernel32::{CreateToolhelp32Snapshot, Process32First, Process32Next, CloseHandle};
use winapi::tlhelp32::{TH32CS_SNAPPROCESS, PROCESSENTRY32};
use winapi::shlobj::INVALID_HANDLE_VALUE;
use winapi::minwindef::MAX_PATH;
use std::mem;
#[cfg(target_os="windows")]
pub fn find_pid_by_name(name: &str) -> Option<u32> {
// Create a snapshot of the current processes
let processes_snap_handle = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
if processes_snap_handle == INVALID_HANDLE_VALUE {
return None
}
// Initialise a process entry. In order to use `Process32First`, you need to set `dwSize`.
let mut process_entry : PROCESSENTRY32 = PROCESSENTRY32 {
dwSize: mem::size_of::<PROCESSENTRY32>() as u32,
cntUsage: 0,
th32ProcessID: 0,
th32DefaultHeapID: 0,
th32ModuleID: 0,
cntThreads: 0,
th32ParentProcessID: 0,
pcPriClassBase: 0,
dwFlags: 0,
szExeFile: [0; MAX_PATH],
};
// Get the first process from the snapshot.
match unsafe { Process32First(processes_snap_handle, &mut process_entry) } {
1 => {
// First process worked, loop to find the process with the correct name.
let mut process_success : i32 = 1;
// Loop through all processes until we find one hwere `szExeFile` == `name`.
while process_success == 1 {
// TODO: Compare `szExeFile` to `name`.
process_success = unsafe { Process32Next(processes_snap_handle, &mut process_entry) };
}
unsafe { CloseHandle(processes_snap_handle) };
Some(0)
},
0|_ => {
unsafe { CloseHandle(processes_snap_handle) };
None
}
}
}
Now, the problem is that winapi::tlhelp32::PROCESSENTRY32::szExeFile
is defined as [CHAR; ::MAX_PATH]
, so basically a [i8; 260]
. As far as I can see from the documentation, there is no standard way to convert this into a string in order to make the comparison with the process being searched for. I had a few ideas of possible solutions:
- Compare the byte values of
name
to the values in the arrayszExeFile
one by one to ensure they’re all found in sequence somewhere in the array. The problem here is that I’d be comparingu8
toi8
, which feels nasty. - Convert
szExeFile
to a string for each process and make surename
exists as a substring. The problem here is working out the best way to get to a string value fromszExeFile
.
In C I’d use the A2T
macro from atlstr.h
: https://msdn.microsoft.com/en-GB/library/87zae4a3(v=vs.110).aspx
I feel like I’m missing something, so any thoughts would be appreciated greatly.