【问题标题】:WinAPI OpenQuery Producing errorsWinAPI OpenQuery 产生错误
【发布时间】:2021-04-04 15:14:40
【问题描述】:

我正在使用winapi-rs crate 并尝试获取 cpu 使用率,但我什至无法做到这一点。

PdhCollectQueryData 在转换十六进制时返回“-2147481643”,然后错误代码是“0x800007D5 (PDH_NO_DATA) 没有数据返回。”这是我面临的问题。

有人可以帮助确定我做错了什么导致“x800007D5 (PDH_NO_DATA) No data to return”吗?我可以在 C++ 中使用它(下面提供的代码),但是在尝试将其转换为 Rust 代码时,它一点也不顺利。

use wmi::{COMLibrary, Variant, WMIConnection};
use std::{collections::HashMap, ptr::null};
use winapi::{ctypes::{c_char, c_void},um::{pdh::*, winnt::{LPCSTR}}};

#[cfg(windows)]
fn main() -> Result<(), Box<dyn std::error::Error>>  {

    const CPU_TIME: LPCSTR = "\\Processor(_Total)\\% Processor Time".as_ptr() as *const i8;

    unsafe  
    {
        //cpuQuery
        let mut hquery: PDH_HQUERY = std::ptr::null_mut();
        let hquery_address: *mut PDH_HQUERY = &mut hquery as *mut *mut _ as *mut *mut c_void;

        //cpuCounter
        let mut hcounter: PDH_HCOUNTER = std::ptr::null_mut();
        let hcounter_address: *mut PDH_HCOUNTER = &mut hcounter as *mut *mut _ as *mut *mut c_void;

        //open query
        PdhOpenQueryA(null(), 0, hquery_address);

        PdhAddCounterA(hquery, CPU_TIME, 0, hcounter_address);
        
        PdhCollectQueryData(hquery);

    }
    Ok(())
}

如果我 println 值,程序完成后某些值返回的示例:

hquery: 0x2541b495e00
hquery_address: 0xce3dafef00
PdhOpenQueryA: 0
PdhCollectQueryData -2147481643

工作 C++ 代码(取自另一个 Stack Overflow 答案,运行时运行良好)

#include <TCHAR.h>
#include <pdh.h>
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <chrono>
#include <thread>  

#pragma comment(lib, "pdh.lib")
using namespace std;

static PDH_HQUERY cpuQuery;
static PDH_HCOUNTER cpuTotal = NULL;
int _tmain(int argc, _TCHAR* argv[])
{
    PdhOpenQuery(NULL, NULL, &cpuQuery);
    PdhAddCounter(cpuQuery, L"\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal);
    PDH_FMT_COUNTERVALUE counterVal;

    PdhCollectQueryData(cpuQuery);
    this_thread::sleep_for(chrono::milliseconds(1000));
    PdhCollectQueryData(cpuQuery);
    PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
    cout << counterVal.doubleValue << "\n";

    getchar();
}

所以,当 C++ 代码运行时,计数器就在那里。查询收集的 rust 代码无法正常工作并产生“x800007D5 (PDH_NO_DATA) No data to return.”,我做错了什么??

【问题讨论】:

  • 我确实已将其全部转换,但删除了其中的一部分,直到我得到产生第一个错误 PdhCollectQueryData(hquery) 的代码。 PdhCollectQueryData(hquery) 给出错误代码:0x800007D5 (PDH_NO_DATA) 没有数据返回,我无法弄清楚为什么会这样。我已经更新了这个问题,希望让它更清楚,我的错:)
  • 任何地方都没有错误处理或错误报告。这在 C++ 中已经是错误的了,而且最肯定地违背了 Rust 所代表的任何东西。移植糟糕的 C++ 代码的第一步通常是添加错误报告。
  • @IInspectable 是的,我明白,C++ 代码不是很好,我从不同的 SO 答案中获取它,因为我只是想看看我是否可以让它工作。肯定会通过错误处理来清理 Rust 代码,道歉。

标签: winapi rust


【解决方案1】:

这是使用 winapi crate 将 C++ 示例直接翻译成 Rust。

正如 IInspectable 在 cmets 中所说,您需要添加一些错误处理,在这种情况下,我添加了一些 assert_eq!

use std::ptr;
// winapi = { version = "0.3.9", features = ["pdh", "winerror"] }
use winapi::{ctypes::c_char, shared::winerror::ERROR_SUCCESS, um::pdh::*};

fn main() {
    unsafe {
        let mut cpu_query: PDH_HQUERY = ptr::null_mut();
        let mut cpu_total: PDH_HCOUNTER = ptr::null_mut();

        let err = PdhOpenQueryA(ptr::null(), 0, &mut cpu_query);
        assert_eq!(err, ERROR_SUCCESS as i32);

        let err = PdhAddCounterA(
            cpu_query,
            b"\\Processor(_Total)\\% Processor Time\0".as_ptr() as *const c_char,
            0,
            &mut cpu_total,
        );
        assert_eq!(err, ERROR_SUCCESS as i32);

        let mut counter_val: PDH_FMT_COUNTERVALUE = std::mem::zeroed();
        let err = PdhCollectQueryData(cpu_query);
        assert_eq!(err, ERROR_SUCCESS as i32);

        std::thread::sleep(std::time::Duration::from_millis(1000));

        let err = PdhCollectQueryData(cpu_query);
        assert_eq!(err, ERROR_SUCCESS as i32);

        let err = PdhGetFormattedCounterValue(
            cpu_total,
            PDH_FMT_DOUBLE,
            ptr::null_mut(),
            &mut counter_val,
        );
        assert_eq!(err, ERROR_SUCCESS as i32);

        println!("{:?}", counter_val.u.doubleValue());
    }
}

【讨论】:

  • 哇,非常感谢!这完美地工作,我将添加更多的错误处理。显然,我还有很多关于 Rust 的知识要学习,但非常感谢。
  • 不客气,很高兴我能帮上忙 :) 如果你正在学习 Rust,那么直接使用 Windows API 肯定会很辛苦
  • 我是新手,我已经在 Rust 中构建了其他小部分(别担心,比我在问题中发布的标准要好得多)但我对系统编程很陌生尤其是 Windows API。但是,我是天生的,从基本程序和解决 Rust 中的 LeetCode 问题到这个 lmao。再次感谢伙计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-30
  • 2016-08-10
  • 2018-11-01
  • 2017-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多