Rust调用WMI的ExecMethod操作xeniface驱动遇问题求助
使用windows-rs 0.48调用Xeniface驱动WMI方法的问题解决
背景
wmi-rs 0.13.1尚未封装ExecMethod,需直接依赖windows-rs 0.48调用WMI方法以操作Xeniface驱动,当前遇到三个核心问题,以下是针对性解决思路及代码参考:
问题1:调用GetMethod返回WBEM_E_ILLEGAL_OPERATION错误
该错误源于目标WMI方法的Provider未暴露元数据,不支持通过GetMethod进行参数自省。无需纠结该方法,直接手动构造输入参数对象即可。
问题2:向ExecMethod传递in_params传入会话名称
跳过GetMethod,手动构造输入参数实例:
- 通过
IWbemServices::GetObject获取目标WMI类的IWbemClassObject实例; - 调用
IWbemClassObject::SpawnInstance(0)创建输入参数的空实例; - 使用
IWbemClassObject::Put方法设置会话名称对应的参数(需确认参数名,比如Python实现中的SessionName); - 将构造好的in_params传入
IWbemServices::ExecMethod。
问题3:从out_params提取ReturnValue返回WBEM_E_NOT_FOUND及自省IWbemClassObject
- WBEM_E_NOT_FOUND解决:先确认方法的实际输出参数名,部分WMI方法的返回值可能不是
ReturnValue,需先枚举属性确认存在性; - 自省IWbemClassObject:调用
IWbemClassObject::GetNames枚举所有属性名称,再逐个调用Get方法获取对应值,示例见下方代码。
代码参考
Python等效实现
import wmi c = wmi.WMI(namespace="root\\virtualization\\v2") service = c.Msvm_VirtualSystemManagementService()[0] params = service.Methods('GetSessionId').InParameters params.SessionName = "MySession" result = service.ExecMethod_('GetSessionId', params) print(result.ReturnValue)
当前Rust代码
use windows::{ core::*, Win32::{ System::Wmi::*, Foundation::*, }, }; fn main() -> Result<()> { let locator = CoCreateInstance::<IWbemLocator>(&WBEM_LOCATOR_CLSID, None, CLSCTX_INPROC_SERVER)?; let services = locator.ConnectServer( &BSTR::from("root\\virtualization\\v2"), None, None, None, 0, None, None, )?; CoSetProxyBlanket( &services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, None, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, None, EOAC_NONE, )?; // 问题1:调用GetMethod失败 let mut method_def = None; let mut in_params_def = None; let hr = services.GetObject( &BSTR::from("Msvm_VirtualSystemManagementService"), 0, None, &mut method_def, None, )?; if let Some(method_def) = method_def { let hr = method_def.GetMethod(&BSTR::from("GetSessionId"), 0, &mut in_params_def, None); println!("GetMethod hr: {:?}", hr); // 返回WBEM_E_ILLEGAL_OPERATION } // 手动构造in_params let mut class_obj = None; services.GetObject(&BSTR::from("Msvm_VirtualSystemManagementService"), 0, None, &mut class_obj, None)?; let mut in_params = None; class_obj.as_ref().unwrap().SpawnInstance(0, &mut in_params)?; let session_name = BSTR::from("MySession"); in_params.as_ref().unwrap().Put( &BSTR::from("SessionName"), 0, &VARIANT::from(&session_name), 0, )?; // 调用ExecMethod let mut out_params = None; let hr = services.ExecMethod( &BSTR::from("Msvm_VirtualSystemManagementService"), &BSTR::from("GetSessionId"), 0, None, in_params.as_ref(), &mut out_params, None, )?; println!("ExecMethod hr: {:?}", hr); // 问题3:提取ReturnValue失败及自省属性 if let Some(out_params) = out_params { let mut value = VARIANT::default(); let hr = out_params.Get(&BSTR::from("ReturnValue"), 0, &mut value, None, None); println!("Get ReturnValue hr: {:?}", hr); // 返回WBEM_E_NOT_FOUND // 枚举所有输出属性 let mut names = Vec::new(); let mut name_ptr = std::ptr::null_mut(); let hr = out_params.GetNames(None, WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY, None, &mut name_ptr); if hr.is_ok() { let mut i = 0; loop { let name = unsafe { *name_ptr.add(i) }; if name.is_null() { break; } names.push(BSTR::from_raw(name).to_string()); i += 1; } unsafe { CoTaskMemFree(name_ptr as _) }; println!("Out params names: {:?}", names); } } Ok(()) }
运行输出
GetMethod hr: Error { code: 0x80041016, message: "非法操作。" } ExecMethod hr: Ok(()) Get ReturnValue hr: Error { code: 0x80041002, message: "找不到指定的对象。" } Out params names: ["SessionId"]
内容的提问来源于stack exchange,提问作者Yann Dirson
相关产品推荐
相关产品推荐

