How to get disk model and serial number for the disk Windows is installed on

sValentin 61 Reputation points
2023-09-20T06:41:06.0766667+00:00

I was trying to get the following to work (I only need it for Windows x64 10+):

#include <iostream>
#include <string>
#include <array>

std::string exec(const char* cmd) {
    std::array<char, 128> buffer;
    std::string result;
    std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(cmd, "r"), _pclose);
    if (!pipe) {
        throw std::runtime_error("popen() failed!");
    }
    while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
        result += buffer.data();
    }
    return result;
}

void main() {
    std::cout << exec("wmic bootconfig get description");
    std::cout << exec("wmic diskdrive where DeviceID='\\.\PHYSICALDRIVE3' get model,serialnumber");
}

The first exec is running fine and giving the right return, but I'm having problems with the second exec, where I'm getting: ERROR: Description = Invalid query. In my search for a fix for that error, I found that because I'm using C++ I should be using native wmi queries, but unfortunately each result with code examples that I found were "like 3 pages" of code. Does anyone know of some more simple examples for wmi queries?

As for the code, I'm trying to get the model and serial number of the disk that the OS is installed on for some unique identification of app install and some other minor checks. And for this, I found that using wmic bootconfig get description, you can parse that result (Description\Device\Harddisk3\Partition1, 3 is the index) and get the index of the disk the OS is installed on, then using that index and wmic diskdrive where DeviceID='\\.\PHYSICALDRIVE3' get model,serialnumber where you change the 3 from PHYSICALDRIVE3 with the index from last command, you get the model and serial number. The code above is just a test to see the commands working, later I was going to parse the result and update the second exec call, right now it's using the index for my PC that I know were the OS is installed.

And yes, I know that the user can simply install the OS on a different disk and so the model and/or serial number would be different, but having to go though all that is enough of a hindrance to actually affect my use case, as I only care when the app is launched, and not on how many machines is installed on, that is IF the user finds that I'm using this verification method in the first place.

Any help is appreciated!

//Edit based on the suggestion on accepted answer I tried with more \ and in the end I made it work. I gave up on trying to use native wmi, and I made it work with CMD call like this which also parses the returns and in the end you get straight model and serial number.

#include <iostream>
#include <string>
#include <array>

std::string exec(const char* cmd) {
    std::array<char, 128> buffer;
    std::string result;
    std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(cmd, "r"), _pclose);
    if (!pipe) {
        throw std::runtime_error("popen() failed!");
    }
    while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
        result += buffer.data();
    }
    return result;
}

void replaceString(std::string& subject, const std::string& search,
    const std::string& replace) {
    size_t pos = 0;
    while ((pos = subject.find(search, pos)) != std::string::npos) {
        subject.replace(pos, search.length(), replace);
        pos += replace.length();
    }
}

void main() {
    std::string index = exec("wmic bootconfig get description");
    index = index.at(index.find_last_of("\\") - 1);
    std::string modelSerialNumber = "wmic diskdrive where DeviceID='\\\\\\\\.\\\\PHYSICALDRIVE" + index + "' get model,serialnumber";
    modelSerialNumber = exec(modelSerialNumber.c_str());
    replaceString(modelSerialNumber, "Model", "");
    replaceString(modelSerialNumber, "SerialNumber", "");
    replaceString(modelSerialNumber, " ", "");
    std::cout << modelSerialNumber;
}

The output will be: KINGSTONSA2000M8250GXXXX_XXXX_XXXX_XXXX_XXXX_XXXX_XXXX_XXXX.. For my use case I needed the model and the serial number united like that.

Windows 10
Windows 10
A Microsoft operating system that runs on personal computers and tablets.
11,477 questions
Windows
Windows
A family of Microsoft operating systems that run across personal computers, tablets, laptops, phones, internet of things devices, self-contained mixed reality headsets, large collaboration screens, and other devices.
5,317 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,690 questions
Windows 11
Windows 11
A Microsoft operating system designed for productivity, creativity, and ease of use.
9,450 questions
0 comments No comments
{count} votes

Accepted answer
  1. Castorix31 84,471 Reputation points
    2023-09-20T07:29:47.5033333+00:00

    It works for me by doubling the "\" :

    (I cannot paste : 4 \ and 2 \ after DeviceID=**)


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.