为何GetLastError返回2?Rust调用CreateFileW创建文件失败排查
解决Rust调用CreateFileW返回错误码2的问题
错误码2对应Windows系统的ERROR_FILE_NOT_FOUND(文件未找到),你的代码存在两处核心问题导致该错误:
1. 字符串转换逻辑错误
CreateFileW要求传入UTF-16编码的宽字符字符串(LPCWSTR本质是*const u16),但你用CString处理字符串——CString是用于生成UTF-8/多字节的C风格字符串,强制转成*const u16会导致系统无法正确解析文件名,最终触发文件未找到错误。
2. 文件创建模式参数错误
你使用了OPEN_EXISTING作为dwCreationDisposition参数,该参数的作用是仅打开已存在的文件,如果目标文件不存在,调用必然失败并返回错误码2。若要创建新文件,需根据需求选择以下参数:
CREATE_NEW:仅当文件不存在时创建,存在则返回错误CREATE_ALWAYS:无论文件是否存在都创建(存在则覆盖)OPEN_ALWAYS:文件存在则打开,不存在则创建
修正后的代码
createfile.rs
use winapi::shared::minwindef::DWORD; use winapi::um::winnt; use winapi::um::errhandlingapi; use winapi::ctypes::*; use winapi::um::minwinbase::*; use winapi::um::fileapi; use winapi::um::handleapi; use std::os::windows::ffi::OsStrExt; use std::ffi::OsStr; // 打印系统错误码 fn print_last_error() { unsafe { let err_code = errhandlingapi::GetLastError(); println!("错误码: {}", err_code); } } // 正确将Rust字符串转换为Windows宽字符指针 fn to_lpcwstr(s: &str) -> *const u16 { OsStr::new(s) .encode_wide() .chain(std::iter::once(0)) // 必须添加宽字符串终止符 .collect::<Vec<_>>() .as_ptr() } fn main() { unsafe { let name = to_lpcwstr("file.rs"); let access: DWORD = winnt::GENERIC_WRITE; let share_mode = winnt::FILE_SHARE_DELETE | winnt::FILE_SHARE_READ | winnt::FILE_SHARE_WRITE; let security_attrs = std::ptr::null_mut(); // 使用CREATE_ALWAYS实现"存在则覆盖,不存在则创建" let disposition = fileapi::CREATE_ALWAYS; let attrs = winnt::FILE_ATTRIBUTE_NORMAL; let template_handle = std::ptr::null_mut(); let handle = fileapi::CreateFileW( name, access, share_mode, security_attrs, disposition, attrs, template_handle, ); if handle == handleapi::INVALID_HANDLE_VALUE { print_last_error(); } else { println!("文件创建成功"); // 必须关闭文件句柄,避免资源泄漏 handleapi::CloseHandle(handle); } } }
Cargo.toml
[package] name = "createfile" version = "0.1.0" edition = "2021" [dependencies] winapi = { version = "0.3.9", features = ["fileapi", "errhandlingapi", "handleapi"] }
额外注意事项
- 转换字符串时必须添加宽字符终止符
0,这是Windows API对宽字符串的强制要求 - 调用
CreateFileW后必须检查返回值是否为INVALID_HANDLE_VALUE,只有此时调用GetLastError才能得到有效错误信息 - 文件操作完成后务必调用
CloseHandle关闭句柄,防止系统资源泄漏
内容的提问来源于stack exchange,提问作者Newbie
相关产品推荐
相关产品推荐

